sql >> データベース >  >> RDS >> Oracle

NULL値でNOTIN選択

    最初の理論:Null(SQL)

    上記のリンクからの私たちにとって最も重要な部分:

    NULLおよび3値論理(3VL)との比較

    Nullはどのデータドメインのメンバーでもないため、「値」とは見なされず、値がないことを示すマーカー(またはプレースホルダー)と見なされます。このため、Nullとの比較では、TrueまたはFalseになることはありませんが、常に3番目の論理結果であるUnknownになります。[8]値10をNullと比較する以下の式の論理結果は不明です:

    SELECT 10 = NULL       -- Results in Unknown
    

    両方の比較:x = NULL およびx <> NULL NULL(不明)と評価されます。

    SQLは3つの論理結果を実装するため、SQL実装は特殊な3値論理(3VL)を提供する必要があります。 SQLの3値論理を管理するルールを以下の表に示します(pとqは論理状態を表します)。含意の定義が異なりますが、SQLではそのような操作は定義されていません。

    +---------+-------------+-------------+-------------+-----------+--------+
    |    p    |        q    |     p OR q  |     p AND q |    p = q  |p != q  |
    +---------+-------------+-------------+-------------+-----------+--------+
    | True    |     True    |     True    |     True    |   True    | False  |
    | True    |     False   |     True    |     False   |   False   | True   |
    | True    |     Unknown |     True    |     Unknown |   Unknown | Unknown|
    | False   |     True    |     True    |     False   |   False   | True   |
    | False   |     False   |     False   |     False   |   True    | False  |
    | False   |     Unknown |     Unknown |     False   |   Unknown | Unknown|
    | Unknown |     True    |     True    |     Unknown |   Unknown | Unknown|
    | Unknown |     False   |     Unknown |     False   |   Unknown | Unknown|
    | Unknown |     Unknown |     Unknown |     Unknown |   Unknown | Unknown|
    +---------+-------------+-------------+-------------+-----------+--------+
    

    WHERE句での不明の影響

    SQL 3値論理は、DMLステートメントとクエリの比較述語のデータ操作言語(DML)で検出されます。 WHERE句を使用すると、DMLステートメントは、述語がTrueと評価された行にのみ作用します。

    つまり、WHERE句はNULLをFALSEとして扱います

    ここで、より単純なケースを考えてみてください:

    SELECT * FROM T1;
    
    |      X |
    |--------|
    |      1 |
    | (null) |
    

    とクエリ:

    SELECT * FROM t1 WHERE x IN (1, NULL);
    

    上記のクエリは、このクエリの短縮形です:

    SELECT * FROM t1 
    WHERE x = 1
      OR  x = NULL
    

    テーブルtの2行目 (x =NULL)この条件は次のようになります:

    WHERE NULL = 1
       OR NULL = NULL
    

    したがって、行x=NULLのこの条件 NULL=1であるため、NULLと評価されます NULL、NULL=NULL はNULLであり、NULL OR NULL もNULLです(上記の表3VLを参照してください)。

    次に、もっと奇妙なケースを考えてみましょう:

    SELECT * FROM t1 WHERE x NOT IN (1, NULL);
    

    この句x NOT IN (1, NULL) NOT ( x IN (1, NULL) )と同等です
    したがって、次と同等です:

    NOT (
      x = 1
      OR
      x = NULL
    )
    

    ド・モルガンの法則によれば、次のようになります。

    NOT ( x = 1 ) AND NOT ( x = NULL )
    

    および(NOT x = yを置き換える場合 x <> yを使用 )これは次と同等でもあります:

     x <> 1 AND x <> NULL
    

    最後の状態をよく見てください:

    WHERE 
    x <> 1 AND x <> NULL
    

    x <> NULLよりもわかっています 常にNULLと評価されます。上記の3VLテーブルから、true AND NULLの両方であることがわかります。 NULLでfalse AND NULL FALSEと評価されるため、条件全体は常にFALSEまたはNULLと評価されますが、TRUEと評価されることはありません。

    したがって、この条件のクエリ:

    SELECT .....
    WHERE x NOT IN ( NULL, whatever)
    

    常に空の結果セットを返します

    そして今、あなたのクエリも興味深いです:

    SELECT * FROM t1
    WHERE (id, val) NOT IN (select id, val from data2);
    

    これは(定数値を使用して)次のように書き換えることができます:

    SELECT * FROM t1
    WHERE (id, val) NOT IN (
           (1, null),
           (2, 2 )
    )
    

    このクエリは、いわゆる行値式を使用しています

    基本的に、このような行値式を使用する条件

    (a, b) = (x, y)
    

    これと同等です:

    a = x AND b = y
    

    したがって、上記のクエリは次のクエリに書き換えることができます:

    SELECT * FROM t1
    WHERE NOT (
       id = 1 AND val = NULL
       OR
       id = 2 AND val = 2
    )
    

    ドモルガンの法則によれば、これは次のようになります。

    SELECT * FROM t1
    WHERE 
       NOT ( id = 1 AND val = NULL )
       AND
       NOT ( id = 2 AND val = 2 )
    

    さらに:

    SELECT * FROM t1
    WHERE 
       ( id <> 1 OR val <> NULL )
       AND
       ( id <> 2 OR val <> 2 )
    

    最初の部分から( id <> 1 OR val <> NULL ) id <> 1の場合にのみ、条件のがtrueと評価されます。 (上記の3VL表を参照してください)、この条件は次のように簡略化できます:

    SELECT * FROM t1
    WHERE 
       ( id <> 1 )
       AND
       ( id <> 2 OR val <> 2 )
    

    さらに(ド・モルガンの法則に従って)次のようになります:

    SELECT * FROM t1
    WHERE 
       id <> 1 AND id <> 2
       OR
       id <> 1 AND  val <> 2
    

    したがって、どちらも(1,1) (2,2)でもありません ソースからdata1 これらの条件を遵守してください。



    1. PostgreSQLJDBCでのスキーマの設定が機能していないようです

    2. 文字列にSQLでアクセント付き文字が含まれているかどうかを確認しますか?

    3. mysql全文検索の失敗

    4. TSQLで分数をhh:mm形式に変換するにはどうすればよいですか?