2016-11-03 18 views
0

私はTeradata 15.10.03.01の問題に直面しています。これはコンマ区切りの列の比較に関するものです。以下のデータと期待される結果を考慮してください。クイック応答が高く評価されます。前もって感謝します。TERADATAカンマ区切りのカラム比較

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

を比較したときに、あなたのヌルを合体する必要がありますアイデア[良い質問をする方法](0120)を参照してください。 – greybeard

答えて

3

マニュアルにはいくつかの情報があります: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ではなく、すべての3つの列を比較しているため、正しい結果が得られない場合があります2つは、あなたのサンプルデータで動作していますが、実際のデータでは失敗する可能性があります。

ありCOALESCEを使用して@DavidCramからsolutionは、(もちろん、あなたが存在しないことが保証されている値を選択する必要があります)です別の外に基づいて参加していますが、彼第二に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

あなたが取得するために時間がかかるしてください。(この質問のほとんどは `以下のスクロールせずに見かけないissue`、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 
) 
; 
+0

実際、私はdnoethの答えが良いのが好きですが、動作して以来私はここに残します:-)。また、あなたの期待した結果では、私はあなたがC4を意味するところでC3と言うと思います(実際にテストテーブルにあるものに基づいて) –

+0

実際には、EXCEPTは3つの列すべてに基づいているので、 2つに基づいていた: – dnoeth

+0

ああ、あなたの答えがnullでの問題を非常にはっきりと説明していて、私もこの種のものに "NOT IN"を使用するファンではないので、あなたはまだ私からupvoteを得ました –