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

NOTINからNOTEXISTSへの変換

    コツをつかめば、それはかなり簡単です:

    SELECT s.S_Fname, s.S_Lname
    FROM STUDENT s
    WHERE s.S_Sex = 'F'
    AND S.S_Id NOT IN(SELECT e.S_Id           -- take this line
            FROM ENROLLMENT e
            WHERE e.Mark < 70);
    

    その行は基本的にS.S_Idを比較します すべてのe.S_Id サブクエリからの値。

    次に、これをNOT EXISTSに変更します。 等価性チェックを行いますS.S_Id = e.S_Id 、サブクエリ内:

    SELECT s.S_Fname, s.S_Lname
    FROM STUDENT s
    WHERE s.S_Sex = 'F'
    AND NOT EXISTS (SELECT e.S_Id          
            FROM ENROLLMENT e
            WHERE (e.Mark < 70)       -- if this is complex, you'll need parentheses
            AND S.S_Id = e.S_Id);
    

    マイナーな変更は、(SELECT e.S_Id ... e.S_Idは実際には必要ありません 。 EXISTSを使用したサブクエリ およびNOT EXISTS 行が返されるかどうかを確認するだけで、列の値は重要ではありません。 SELECT *を置くことができます またはそこに定数(SELECT 1 一般的です)またはSELECT NULL またはSELECT 1/0 (はい、それでうまくいきます!):

    SELECT s.S_Fname, s.S_Lname
    FROM STUDENT s
    WHERE s.S_Sex = 'F'
    AND NOT EXISTS (SELECT 1
            FROM ENROLLMENT e
            WHERE e.Mark < 70  
            AND S.S_Id = e.S_Id);
    

    もう1つの重要な考慮事項は、この方法で変換を行う場合、(一見同等の)NOT EXISTSであるということです。 およびNOT IN クエリの記述は、両方のS_Idの場合にのみ、実際には同等です。 列はNULL可能ではありません。 e.S_Idの場合 列はNULL可能であり、NOT IN クエリ全体で行がまったく返されない場合があります(x NOT IN (a, b, c, ...) x<>a AND x<>b AND ...と同等です a,b,c...のいずれかである場合、その条件は真にはなりません。 NULLです 。)

    同様の理由で、s.S_Idの場合、結果は異なります。 null許容型です(おそらく主キーであるため、この場合はあまりありそうにありませんが、それ以外の場合は重要です)。

    したがって、ほとんどの場合、NOT EXISTSを使用することをお勧めします。 、どちらかの列がnull許容であっても動作が異なるため(S.S_Id = e.S_Id チェックは以前にnullの行を破棄します)、通常、この動作が必要です。質問には多くの詳細があります: NOT IN vs NOT EXISTS 、@MartinSmithによる回答。 NOT INを変換する方法もあります NOT EXISTS nullに関連する(不快な)動作を維持します。



    1. タグをデータベースに保存するためのベストプラクティスは?

    2. Rails4を使用したJSONデータ型のPostgres演算子

    3. 実行は、SqlFiddleでストアドプロシージャをトリガーします。 Mysql

    4. SQL再帰CTE:プロパティによってリンクされたオブジェクトの検索