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

Posted

技术标签:

【中文标题】Netezza 创建不在两个原始表中的记录表【英文标题】:Netezza Create Table of records that are not in both original tables 【发布时间】:2014-12-10 09:25:46 【问题描述】:

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

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

通常要做到这一点,我会获取原始表的横向副本,使用简单的连接和更新语句为确实出现在两者中的每条记录添加一个标志,然后删除所有带有标志的记录。但是,由于涉及的记录数量巨大,而且我的资源是共享的,这种方法耗时太长。

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

谢谢!

【问题讨论】:

您可以使用完全连接来查找差异 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 很有魅力 :) 随意添加作为答案,我知道必须有一个简单的解决方案 :) 【参考方案1】:

从您的 cmets 看来,您实际上是在询问查找 key 列 不存在于两者中的行,而不是您的问题似乎提出的问题(整个 记录 不在两者中)。

如果是这种情况,那么 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 几乎肯定会使查询运行得更慢,但如果你需要它,它就在那里。

【讨论】:

【参考方案2】:

你可以使用全连接来查找差异

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

【讨论】:

只要您比较/加入的列没有 NULL 值,这将起作用,因为 NULL 不会加入 NULL。这个答案意味着他们不会通过调用列 key1 来实现,但情况可能并非总是如此。 我认为两者都不能为 NULL。那么这种比较有什么意义呢? 似乎对我有用,键列不能有空值,因为它们是唯一键 在需要比较一组没有键的数据的情况下(例如,从具有与维度中使用的代理键无关的自然键的源数据填充缓慢变化的维度时表),您将需要根据该 nat 键定位记录,然后确定其他列是否不同。如果您所做的只是在 table1 和 table2 中查找具有不在两者中的非空键列的行,则完全联接将起作用。当您必须比较可能为非空的行的其余列时(例如更改检测),该方法将失败。

以上是关于Netezza 创建不在两个原始表中的记录表的主要内容,如果未能解决你的问题,请参考以下文章

从 netezza 表中清除记录

如何使用 DB2 sql 检查不在两个表中的记录以获取另一个第三个表中的日期?

使用 Python 从 Netezza 中的表列表中获取记录计数

为啥我不能直接使用不在函数后面的另一个表中的列?

Netezza 性能优化

Hive表和Netezza表的匹配记录