我在Teradata 15.10.03.01中面临以下问题。这是关于逗号分隔列比较。考虑下面提到的数据和预期结果。
CREATE MULTISET TABLE TESTDB.TESTTABLE1 ,NO FALLBACK ,
NO BEFORE JOURNAL,
NO AFTER JOURNAL,
CHECKSUM = DEFAULT,
DEFAULT MERGEBLOCKRATIO
(
A VARCHAR(250) CHARACTER SET LATIN NOT CASESPECIFIC,
B VARCHAR(250) CHARACTER SET LATIN NOT CASESPECIFIC,
C VARCHAR(250) CHARACTER SET LATIN NOT CASESPECIFIC)
PRIMARY INDEX ( A );
CREATE MULTISET TABLE TESTDB.TESTTABLE2 ,NO FALLBACK ,
NO BEFORE JOURNAL,
NO AFTER JOURNAL,
CHECKSUM = DEFAULT,
DEFAULT MERGEBLOCKRATIO
(
A VARCHAR(250) CHARACTER SET LATIN NOT CASESPECIFIC,
B VARCHAR(250) CHARACTER SET LATIN NOT CASESPECIFIC,
C VARCHAR(250) CHARACTER SET LATIN NOT CASESPECIFIC)
PRIMARY INDEX ( A );
INSERT INTO TESTDB.TESTTABLE1 VALUES('A1','B1','C1');
INSERT INTO TESTDB.TESTTABLE1 VALUES('A2','B2','C2');
INSERT INTO TESTDB.TESTTABLE1 VALUES('A3',NULL,'C3');
INSERT INTO TESTDB.TESTTABLE1 VALUES('A4',NULL,'C4');
INSERT INTO TESTDB.TESTTABLE1 VALUES(NULL,'B5','C5');
INSERT INTO TESTDB.TESTTABLE1 VALUES(NULL,'B6','C6');
INSERT INTO TESTDB.TESTTABLE1 VALUES(NULL,NULL,'C7');
INSERT INTO TESTDB.TESTTABLE1 VALUES(NULL,NULL,'C8');
INSERT INTO TESTDB.TESTTABLE2 VALUES('A1','B1','C1');
INSERT INTO TESTDB.TESTTABLE2 VALUES('A3',NULL,'C3');
INSERT INTO TESTDB.TESTTABLE2 VALUES(NULL,'B5','C5');
INSERT INTO TESTDB.TESTTABLE2 VALUES(NULL,NULL,'C7');
SELECT * FROM TESTDB.TESTTABLE1;
A B C
-------------
A1 B1 C1
A2 B2 C2
A3 C3
A4 C4
B5 C5
B6 C6
C7
C8
SELECT * FROM TESTDB.TESTTABLE2;
A B C
------------
A1 B1 C1
A3 C3
B5 C5
C7
预期结果:
A B C
-------------
A2 B2 C2
A4 C3
B6 C6
我尝试使用以下查询,但它没有返回任何记录。
SELECT T1.A,T1.B,T1.C
FROM TESTDB.TESTTABLE1 T1
WHERE (T1.A,T1.B)
NOT IN
(
SELECT T2.A,T2.B
FROM TESTDB.TESTTABLE2 T2
)
;
如何构建查询?
为什么我的查询没有返回任何记录?
答案 0 :(得分:3)
手册中有一些信息:Behavior of Nulls for NOT IN,但根据标准SQL,此行为不正确。
您的查询不应返回任何行,因为与NULL
的任何比较都会导致UNKNOWN
,因此子查询返回的单个NULL将导致空结果。
因此,只需按照每个DBMS的基本推荐,永远不要将NOT IN
用于NULLable列。
通常的重写基于NOT EXISTS
:
SELECT T1.A,T1.B,T1.C
FROM TESTDB.TESTTABLE1 T1
WHERE NOT EXISTS
(
SELECT *
FROM TESTDB.TESTTABLE2 T2
WHERE T1.A = T2.A
AND T1.B = T2.B
)
;
但在你的情况下,这也不会返回你的预期结果,因为NULL不等于NULL。
您需要一个设置操作,EXCEPT
(或MINUS
),它将NULL视为等于:
SELECT * FROM TESTDB.TESTTABLE1
EXCEPT
SELECT * FROM TESTDB.TESTTABLE2
编辑:
EXCEPT
可能无法提供正确的结果,因为它会比较所有三列而不是两列,它会对您的示例数据起作用,但可能会因您的实际数据而失败。
来自@DavidCram的solution使用COALESCE
(当然你需要选择一个保证不存在的值),另一个基于外部联接,但是你需要一个在第二个表中定义为NOT NULL
的列:
SELECT T1.*
FROM TESTDB.TESTTABLE1 T1
LEFT JOIN TESTDB.TESTTABLE2 T2
ON (T1.A = T2.A OR (T1.A IS NULL AND T2.A IS NULL))
AND (T1.B = T2.B OR (T1.B IS NULL AND T2.B IS NULL))
WHERE T2.C IS NULL
;
这可以避免COALESCE
,并且仍然可以加入主索引。
答案 1 :(得分:1)
比较它们时需要合并空值
SELECT T1.A,T1.B,T1.C
FROM TESTTABLE1 T1
WHERE (COALESCE(T1.A,''),COALESCE(T1.B,''))
NOT IN
(
SELECT COALESCE(T2.A,''),COALESCE(T2.B,'')
FROM TESTTABLE2 T2
)
;