0Pricing
SQL Academy · レッスン

アンチ結合とセミ結合(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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. CROSS JOINと直積
  2. ラテラル結合(LATERAL JOIN)
  3. アンチ結合とセミ結合(NOT EXISTS)
  4. 複数テーブル結合の性能チューニング
← SQL Academyに戻る