このタスクには基本的に4つの手法があり、それらはすべて標準SQLです。
NOT EXISTS
多くの場合、Postgresで最速です。
SELECT ip
FROM login_log l
WHERE NOT EXISTS (
SELECT -- SELECT list mostly irrelevant; can just be empty in Postgres
FROM ip_location
WHERE ip = l.ip
);
また、考慮してください:
- EXISTSサブクエリで読みやすいものは何ですか?
LEFT JOIN / IS NULL
時々これが最速です。多くの場合、最短です。多くの場合、NOT EXISTSと同じクエリプランになります 。
SELECT l.ip
FROM login_log l
LEFT JOIN ip_location i USING (ip) -- short for: ON i.ip = l.ip
WHERE i.ip IS NULL;
EXCEPT
短い。より複雑なクエリに簡単に統合することはできません。
SELECT ip
FROM login_log
EXCEPT ALL -- "ALL" keeps duplicates and makes it faster
SELECT ip
FROM ip_location;
(ドキュメントごとに)注意してください:
EXCEPT ALLでない限り、重複は排除されます 使用されます。
通常、ALLが必要になります キーワード。気にしない場合でも、クエリが高速になるため、引き続き使用してください。 。
NOT IN
NULLなしでのみ有効 値、またはNULLを処理することがわかっている場合 ちゃんと。私はしません この目的のためにそれを使用してください。また、テーブルが大きくなるとパフォーマンスが低下する可能性があります。
SELECT ip
FROM login_log
WHERE ip NOT IN (
SELECT DISTINCT ip -- DISTINCT is optional
FROM ip_location
);
NOT IN NULLの「トラップ」を運ぶ いずれかの側の値:
- 結合が存在しないレコードを検索する
MySQLを対象としたdba.SEに関する同様の質問:
- 2番目の列の値が最初の列に存在しない行を選択します