【问题标题】:TERADATA comma separated column comparisonTERADATA 逗号分隔列比较
【发布时间】:2023-03-16 09:25:01
【问题描述】:

我在 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
    )
    ;

如何构建查询?

为什么我的查询没有返回任何记录?

【问题讨论】:

  • (这个问题的大部分呈现为一个单一的代码块,below issue 不滚动不明显。请花时间了解How to ask a good question。)

标签: sql teradata


【解决方案1】:

手册中有一些信息:Behavior of Nulls for NOT IN,但是根据标准 SQL,这种行为是不正确的。

您的查询不应返回任何行,因为与 NULL 的任何比较结果都为 UNKNOWN,因此子查询返回的单个 NULL 将导致空结果。

因此,只需遵循每个 DBMS 的基本建议,切勿将NOT IN 用于可空列

通常的重写是基于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(当然您需要选择一个保证不存在的值),另一个基于外部联接,但您需要一个定义为@ 的列987654333@在第二张桌子上:

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,并且可能仍会加入主索引。

【讨论】:

    【解决方案2】:

    比较时需要合并空值

    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
    )
    ;
    

    【讨论】:

    • 实际上,我更喜欢 dnoeth 的回答,但我会留在这里,因为它有效 :-)。同样在您的预期结果中,我认为您说 C3 的意思是 C4(基于您的测试表中的实际内容)
    • 事实上,我的答案可能不起作用,因为 EXCEPT 基于所有三列,而 NOT IN 基于两列:)
    • 哦,好吧,您仍然得到了我的支持,因为您的回答非常清楚地解释了 null 的问题,而且我也不喜欢在这类事情上使用“NOT IN”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多