次のようなSQLがあります。
SELECT * FROM foo WHERE foo.bar IN (SELECT foobar.bar FROM foobar)
これは良くないですよね?入れ子になった SELECT によって速度が低下しますか? このようなものをどのように照会すればよいですか?
IN 句は完全に有効な SQL ですが、常に推奨される方法とは限りません。foo.bar
インデックスが作成されていても、MySQL のパフォーマンスがかなり悪いことがよくあります。
結合に変更する場合、最初のテーブルの各行の結合条件に一致する行が 2 番目のテーブルに複数ある場合、結合により複数の結果行が生成されるため、注意が必要です。これが可能な場合、結合は次のようになります。
SELECT f.*
FROM foo f
INNER JOIN (SELECT DISTINCT bar FROM foobar) fb USING (bar);
最終的な答えは、EXPLAIN を使用して、さまざまな形式のクエリがどのように実行されるかを確認する必要があるということです。しかし、そもそもパフォーマンスの問題が発生していない場合でも、心配する必要はありません。
に存在f.bar
しないすべての行が必要な場合はfoobar
、NOT IN
通常、最も簡潔な記述方法です。しかし、次のように書くこともできますLEFT OUTER JOIN
:
SELECT f.*
FROM foo f
LEFT OUTER JOIN foobar fb USING (bar)
WHERE fb.bar IS NULL
この場合、一致しない行のみを報告しているため、サブクエリは必要ありません。したがって、結果に複数の一致が存在することは明らかにありません。
これを次のように書き換えることもできます。
Select
*
From
foo f
Where
Exists ( -- If you want the opposite, put Not in front here
Select 'x'
From foobar fb
Where f.bar = fb.bar
);
何年にもわたって、さまざまな DBMS がさまざまな形式のいずれかでクエリをより適切に処理してきましたが、それらはすべて同等です。私が試したもののほとんどは、現在、両方に対して同じ計画を生成できます。ただし、mysqlで試したことはありません。