如何在postgres中“加入”两个表

时间:2015-04-21 11:28:06

标签: postgresql distinct

我有两个表包含几乎相同的东西。但他们从不同来源获得数据,而在完美世界中他们是相同的。实践 - 他们不同。目标是找到匹配的记录并相互连接,然后结果是不匹配的记录。

first_table:

id1,date1,value1

second_table:

id2,date2,value2

我创建第三个表" joiner":

ID1,ID2

现在使用这个咒语:

INSERT INTO joiner (SELECT id1,id2  FROM first_table,second_table WHERE value1=value2 and date1=date2 ORDER BY date1,date2,id1,id2);

(排序很重要,因为有时候会丢失一些包,所以我必须稍后添加)

一切都会很棒,但是......有时会有不止一条记录具有相同的值和日期,并且无法识别它。接受的解决方案是首先从first_table加入第一个来自second_table,第二个来自first_table,第二个来自second_table等。

这就是问题所在。

因为joiner在每列上都有唯一键 - insert会引发unique_violation错误,因为示例结果是:

id1|id2
-------
 a1| b1
 a1| b2
 a2| b1
 a2| b2

如果我使用SELECT distinct id1,id2当然没有任何变化(a1,b1)!=(a1,b2) 如果我在(id1)id1,id2上使用SELECT distinct - 结果有时是:

id1|id2
-------
 a1| b1
 a2| b1

我尝试使用WHERE NOT EXISTS(SELECT 1 FROM first_table f WHERE f.id1<> first_table.id1)AND NOT EXISTS(SELECT 1 FROM second_table s WHERE s.id2<> second_table.id2) - 仍然没有

我尝试使用EXCEPTION添加函数,但这也是错误的 - 因为它引发了异常,但是joiner仍然是空的......

有什么想法吗?

更新 我不知道为什么有些人在没有任何评论的情况下投票支持我的问题。也许是因为它还不够清楚 - 特别是对于那些例子:

first_table:

id1, value1, date1

1,10, 2015-03-01
2,11, 2015-03-01
3,10, 2015-03-01
4,14, 2015-03-02

second_table:

id2, value2, date2

1,10, 2015-03-01
2,11, 2015-03-01
3,10, 2015-03-01
4,15, 2015-03-02

预期的木匠

id1, id2

1,1
2,2
3,3

正如你所看到的,id1 = 4而id2 = 4并没有木匠 - 因为价值不同(审计员需要手工检查和修复)。

并且id1 = 1和id1 = 3存在问题 - 相同,因此没有uniqness的joiner看起来像:

id1, id2

1,1
1,3
2,2
3,1
3,3

哪个错了。

1 个答案:

答案 0 :(得分:1)

问题的解决方案是使用row_number()枚举每个表中常见日期/值对的值。

您的查询也可以通过其他方式进行改进:

  • 使用insert时,请始终列出列。
  • 学习使用正确的显式join语法。简单规则:永远不要在from子句中使用逗号。
  • 使用表别名指定列的来源。

查询是:

INSERT INTO joiner(id1, id2)
    SELECT id1, id2
    FROM (select ft.*, row_number() over (partition by value1, date1 order by value1) as seqnum
          from first_table ft
         ) ft JOIN
         (select st.*, row_number() over (partition by value2, date2 order by value2) as seqnum
          from second_table st
         ) st
         ON ft.value1 = st.value2 and ft.date1 = st.date2 and ft.seqnum = st.seqnum
    ORDER BY ft.date1, st.date2, ft.id1, st.id2;

我不认为order by很重要,但是因为您认为它是相关的,所以我将其留下来。

相关问题