更新:
私のブログのこれらの記事では、方法の違いについて詳しく説明しています。
-
NOT INvs.存在しないvs.LEFT JOIN / IS NULL:SQL Server -
NOT INvs.存在しないvs.LEFT JOIN / IS NULL:PostgreSQL -
NOT INvs.存在しないvs.LEFT JOIN / IS NULL:Oracle -
NOT INvs.存在しないvs.LEFT JOIN / IS NULL:MySQL
このようなクエリを実行するには、次の3つの方法があります。
-
LEFT JOIN / IS NULL:SELECT * FROM common LEFT JOIN table1 t1 ON t1.common_id = common.common_id WHERE t1.common_id IS NULL -
存在しません:SELECT * FROM common WHERE NOT EXISTS ( SELECT NULL FROM table1 t1 WHERE t1.common_id = common.common_id ) -
NOT IN:SELECT * FROM common WHERE common_id NOT IN ( SELECT common_id FROM table1 t1 )
table1.common_idの場合 null許容型ではなく、これらのクエリはすべて意味的に同じです。
null許容の場合、 NOT IN IN なので、違います (したがって、 NOT IN ) NULLを返します 値がNULLを含むリストのいずれにも一致しない場合 。
これは紛らわしいかもしれませんが、これの代替構文を思い出すと、より明白になる可能性があります:
common_id = ANY
(
SELECT common_id
FROM table1 t1
)
この条件の結果は、リスト内のすべての比較のブール積です。もちろん、単一の NULL 値はNULLを生成します 結果全体をレンダリングする結果NULL
common_idと明確に言うことはできません。 値の少なくとも1つがNULLであるため、はこのリストのいずれにも等しくありません。 。
次のデータがあるとします。
common
--
1
3
table1
--
NULL
1
2
LEFT JOIN / IS NULL およびNOTEXISTS 3を返します 、 NOT IN 何も返さない (常に FALSEのいずれかに評価されるため またはNULL 。
MySQLで 、null許容でない列の場合、 LEFT JOIN / IS NULL およびNOTIN NOT EXISTS よりも少し(数パーセント)効率的です 。列がnull許容の場合、 NOT EXISTS 最も効率的です(ここでも、それほど多くはありません)。
Oracle内 、3つのクエリすべてで同じプランが生成されます( ANTI JOIN 。
SQL Server内 、 NOT IN /存在しません LEFT JOIN / IS NULL であるため、より効率的です。 ANTI JOINに最適化することはできません オプティマイザによって。
PostgreSQLで 、 LEFT JOIN / IS NULL およびNOTEXISTS NOT INよりも効率的です 、sineそれらは Anti Joinに最適化されています 、 NOT IN ハッシュされたサブプランを使用します (または単純な<code>サブプラン サブクエリが大きすぎてハッシュできない場合)