如何 "join" postgres 中的两个表

how to "join" two tables in postgres

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

first_table:

id1, date1, value1

second_table:

id2、date2、value2

我创建第三个table"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 加入,等等

问题来了。

因为连接器在每一列上都有唯一键 - 插入会引发 unique_violation 错误,因为示例结果是:

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

如果我使用 SELECT 不同的 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 存在问题 - 相同,因此没有唯一性的连接器看起来像:

id1, id2

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

这是错误的。

您的问题的解决方案是使用 row_number() 枚举每个 table.

中常见 date/value 对的值

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

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

查询是:

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 不重要,但我保留它是因为您认为它相关。