このタスクには基本的に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番目の列の値が最初の列に存在しない行を選択します