Netezza创建不在两个原始表中的记录表

时间:2014-12-10 09:25:46

标签: sql join distinct netezza

嗨,这可能是一个简单的问题,但是:

我有2个表,其中一个是2900万个条目,另一个是4000万个,有很大的重叠。我想创建一个第三个表,其中只包含不会出现在两个表中的记录。

通常为了做到这一点,我会采用原始​​表的横向副本,为使用简单连接和更新语句在两者中出现的每个记录添加一个标志,然后使用标志删除所有记录。但是由于涉及大量记录和我的资源的共享性质,这种方法花了太长时间。

有没有更直接的方法来制作这样的表格?

谢谢!

2 个答案:

答案 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