PostgreSQL'NOTIN 'およびサブクエリ


89

私はこのクエリを実行しようとしています:

SELECT mac, creation_date 
FROM logs 
WHERE logs_type_id=11
AND mac NOT IN (select consols.mac from consols)

しかし、結果は得られません。私はそれをテストしました、そして私は構文に何か問題があることを知っています。MySQLでは、このようなクエリは完全に機能します。テーブルにmac存在しない行があることを確認するために行を追加しましたconsolsが、それでも結果は得られません。


4
あるconsols.mac列には、NULLまたはNOT NULL
マークバイアーズ2011

回答:


166

NOT INを使用するときは、どの値もNULLでないことを確認する必要があります。

SELECT mac, creation_date 
FROM logs 
WHERE logs_type_id=11
AND mac NOT IN (
    SELECT mac
    FROM consols
    WHERE mac IS NOT NULL -- add this
)

4
注:常にNULL(および重複)を削除するWHERE mac IS NOT NULLため、サブクエリの句は必要ありませんIn(...)。セットにNULLを含めることはできないため
wildplasser 2015年

7
@wildplasser私はそれについて知らない。を追加するまで、それは私にとってはうまくいきませんでしたIS NOT NULL。ネストされたものSELECTはいくつかを返していましたNULLS、そしてそれはつまずきましたIN(SELECT...)
robins35 2017

2
なぜIS NOT NULLこれが機能するのかについて説明していただければ幸いです。
mbarkhau 2017

7
との比較が真でも偽でもないためNULLNOT IN句での使用は機能しないようNULLです。sqlbadpractices.com/using-not-in-operator-with-null-values
mbarkhau

2
is not nullサブクエリが一致する値を生成せず、少なくとも1つのnull値を生成する場合、クエリは行を返しません。現在の(バージョン10)PostgreSQLマニュアルのセクション9.22から: "[…]等しい右側の値がなく、少なくとも1つの右側の行がnullを生成する場合、NOTIN構文の結果はnullになります。trueではありません。」
クリストファールイス

29

NOT INを使用する場合は、nullケースをサイレントに処理するNOTEXISTSも考慮する必要があります。PostgreSQLWikiも参照してください

SELECT mac, creation_date 
FROM logs lo
WHERE logs_type_id=11
AND NOT EXISTS (
  SELECT *
  FROM consols nx
  WHERE nx.mac = lo.mac
  );

3
NOT EXISTSvsを使用するとパフォーマンスが大幅に低下することにも注意してください... NOT IN
IcanDivideBy0 2016年

1
@ IcanDivideBy0ほとんどの場合、同じクエリプランを生成します。あなたはそれをテストしましたか?
wildplasser 2016年

1
サブクエリの場合、NOTEXISTSではなくNOTINを使用するとパフォーマンスが向上します。参照してくださいwiki.postgresql.org/wiki/Don%27t_Do_This#Don.27t_use_NOT_IN
Gerbrand

8

LEFTJOINおよびISNULL条件を使用することもできます。

SELECT 
  mac, 
  creation_date 
FROM 
  logs
    LEFT JOIN consols ON logs.mac = consols.mac
WHERE 
  logs_type_id=11
AND
  consols.mac IS NULL;

「mac」列のインデックスは、パフォーマンスを向上させる可能性があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.