嗨,这可能是一个简单的问题,但是:
我有2个表,其中一个是2900万个条目,另一个是4000万个,有很大的重叠。我想创建一个第三个表,其中只包含不会出现在两个表中的记录。
通常为了做到这一点,我会采用原始表的横向副本,为使用简单连接和更新语句在两者中出现的每个记录添加一个标志,然后使用标志删除所有记录。但是由于涉及大量记录和我的资源的共享性质,这种方法花了太长时间。
有没有更直接的方法来制作这样的表格?
谢谢!
答案 0 :(得分:1)
从您的评论中可以看出,您实际上是在询问查找键列并非存在于两者中的行,而不是您的问题似乎构成的行(整个记录两者都没有。
如果是这种情况,那么FULL JOIN方法将适合您,但如果您(或其他人)需要比较完整记录(可能与NULL),这里是比较我所知道的方法。
create table tableA (col1 integer, col2 integer);
create table tableB (col1 integer, col2 integer);
insert into tableA values (1,1);
insert into tableB values (1,1);
insert into tableA values (NULL,1);
insert into tableB values (NULL,1);
insert into tableA values (2,2);
insert into tableA values (NULL,2);
insert into tableB values (3,3);
insert into tableB values (NULL,3);
TESTDB.ADMIN(ADMIN)=> select * from tableA order by col1, col2;
COL1 | COL2
------+------
| 1
| 2
1 | 1
2 | 2
(4 rows)
TESTDB.ADMIN(ADMIN)=> select * from tableB order by col1, col2;
COL1 | COL2
------+------
| 1
| 3
1 | 1
3 | 3
(4 rows)
在这种情况下,FULL JOIN将包含(NULL,1)元组并加入它,即使它在两个表中。当然,这种行为是由于我们依赖NULL而不加入。当您比较的列不能为NULL时,这种方法应该可以正常工作。
select A.Col1 A_Col1, A.Col2 A_Col2, B.Col1 B_Col1, B.Col2 B_Col2
from tableA a FULL JOIN tableB b
on a.COL1 = b.COL1
and a.COL2 = b.COL2
where a.COL1 is null
or b.COL1 is null;
A_COL1 | A_COL2 | B_COL1 | B_COL2
--------+--------+--------+--------
| | 3 | 3
| 1 | |
2 | 2 | |
| 2 | |
| | | 3
| | | 1
无论NULL约束如何都可以使用的方法是使用EXCEPT。 UNION,INTERSECT和EXCEPT都将两个NULL列视为匹配。这种方法还具有以正确的非连接形状返回行的优点。
(select * from tableA
except
select * from tableB)
union
(select * from tableB
except
select * from tableA);
COL1 | COL2
------+------
| 2
| 3
2 | 2
3 | 3
(4 rows)
另一种可能性是使用NOT IN,但仅限于适当的情况。 Netezza中的NOT IN表示为JOIN,并且在最严格的意义上,当NULL处于播放状态时,它应该与FULL JOIN类似地失败。它确实如此,因为它返回(NULL,1)行。
select * from tableA
where (col1, col2 )not in (select * from tableB)
union
select * from tableB
where (col1, col2) not in (select * from tableA);
COL1 | COL2
------+------
| 1
| 2
| 3
2 | 2
3 | 3
(5 rows)
然而,有些人更喜欢更直接的"理解NOT IN会将NULL与NULL匹配,并且你可以(取决于你的版本)请求这种行为(它将封面下的查询转换为JOIN与" OR ... ISNULL"条件)。
set enable_notin_transformation=1;
select * from tableA
where (col1, col2 )not in (select * from tableB)
union
select * from tableB
where (col1, col2) not in (select * from tableA);
set enable_notin_transformation=0;
COL1 | COL2
------+------
| 2
| 3
2 | 2
3 | 3
(4 rows)
设置enable_notin_transformation几乎肯定会使查询运行得更慢,但如果你需要它,那就在那里。
答案 1 :(得分:0)
您可以使用完整联接来查找差异
SELECT *
FROM table1 AS t1
FULL JOIN table2 AS t2 ON t1.key1 = t2.key2
WHERE t1.key1 IS NULL OR t2.key2 IS NULL