アンチ結合とセミ結合(NOT EXISTS)
EXISTS/NOT EXISTSを使い、「AにあってBに一致しない行」(アンチ結合)と「AにあってBに少なくとも1つ一致する行」(セミ結合)を見つけます。
「アンチ結合とセミ結合(NOT EXISTS)」はCoddyKit上の無料SQL Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSQL Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 SQL Academyコースには全4レッスンが含まれています。
セミ結合:「少なくとも1件の一致がある」
B に少なくとも1つ一致する行がある A の行を、A の列だけ返します。SQL では、EXISTS または IN を使ってセミ結合を実装します。
EXISTS によるセミ結合
少なくとも1件の注文を行ったユーザーを取得します。
SELECT u.* FROM users u
WHERE EXISTS (
SELECT 1 FROM orders o WHERE o.user_id = u.id
);IN によるセミ結合
同じ結果を、別の書き方で取得します。
SELECT * FROM users
WHERE id IN (SELECT user_id FROM orders);EXISTS がよく優れている理由
EXISTS は短絡評価を行い、外側の各行について最初の一致が見つかると処理を停止します。IN は内側の集合全体をマテリアライズすることがあります。最新のプランナーは同じ実行計画に最適化することも多いですが、内側の集合が非常に大きい場合は EXISTS のほうが安全です。
反結合:「一致がない」
一度も注文を行っていないユーザーを取得する、代表的な3つの形式です。
-- NOT EXISTS (preferred):
SELECT u.* FROM users u
WHERE NOT EXISTS (
SELECT 1 FROM orders o WHERE o.user_id = u.id
);
-- LEFT JOIN ... IS NULL:
SELECT u.* FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE o.id IS NULL;
-- NOT IN (risky with NULLs):
SELECT * FROM users WHERE id NOT IN (SELECT user_id FROM orders);NOT IN が危険な理由
内側のサブクエリに NULL が含まれると、NOT IN は NULL を返します。WHERE は述語が NULL の行を除外するため、結果として行が0件になります。NOT EXISTS にはこの問題がありません。
プランナーによる最適化
最新の PostgreSQL は EXISTS と NOT EXISTS をセミ結合や反結合のパターンとして認識し、ハッシュ結合で実行することがあります。
EXPLAIN ANALYZE
SELECT u.* FROM users u
WHERE NOT EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id);
-- → Hash Anti Join複数列の反結合
複合キーを使用します。
SELECT * FROM order_items oi
WHERE NOT EXISTS (
SELECT 1 FROM shipments s
WHERE s.order_id = oi.order_id
AND s.line_no = oi.line_no
);EXISTS と追加条件によるセミ結合
内側のサブクエリにフィルタを追加します。
SELECT u.* FROM users u
WHERE EXISTS (
SELECT 1 FROM orders o
WHERE o.user_id = u.id
AND o.status = 'paid'
AND o.created_at >= NOW() - INTERVAL '30 days'
);相関列にインデックスを付ける
EXISTS と NOT EXISTS のどちらでも、内側のサブクエリは外側の行のキーでフィルタリングします。そのキーにインデックスがないと、外側の各行についてスキャンが実行されます。
CREATE INDEX orders_user_id_idx ON orders(user_id);LEFT JOIN ... IS NULL を使用する場合
不一致側の列も必要なダッシュボードでは、LEFT JOIN の形式が自然です。純粋な反結合の意味を表す場合は、NOT EXISTS のほうが明確です。
SQL の先へ:ブルームフィルタ
非常に大きな反結合では、ブルームフィルタによる事前フィルタが役立つことがあります。PostgreSQL では、bloom 拡張機能を通じて bloom インデックスを利用できます。
まとめ
セミ結合 = 「一致がある」、反結合 = 「一致がない」です。
- セミ結合には EXISTS
- 反結合には NOT EXISTS(NULL に安全)
- 相関列にインデックスを付ける
- 内側の値に NULL が含まれないと保証できない限り、NOT IN は避ける
クイックチェック
一度も注文を行っていないユーザーを取得したいとします。最も安全で慣用的な SQL はどれですか?
よくある質問
「アンチ結合とセミ結合(NOT EXISTS)」レッスンは無料ですか?
はい。「アンチ結合とセミ結合(NOT EXISTS)」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、SQL Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 SQL Academyコースには全4レッスンが含まれています。
「アンチ結合とセミ結合(NOT EXISTS)」で何を学びますか?
EXISTS/NOT EXISTSを使い、「AにあってBに一致しない行」(アンチ結合)と「AにあってBに少なくとも1つ一致する行」(セミ結合)を見つけます。 ブラウザで直接実行するハンズオンコードでSQL Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
SQL Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのSQL Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「アンチ結合とセミ結合(NOT EXISTS)」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このSQL Academyレッスンでコードを書いて実行できますか?
はい。すべてのSQL Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- CROSS JOINと直積
- ラテラル結合(LATERAL JOIN)
- アンチ結合とセミ結合(NOT EXISTS)
- 複数テーブル結合の性能チューニング