0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PostgreSQLで「一件もない場合」にデータを取得する方法(NOT EXISTS 編)

Posted at

PostgreSQL で 関連テーブルに行が存在しない場合 に特定のデータを取得したいとき、NOT EXISTS は非常に有効です。
結合(LEFT JOIN + IS NULL)を使う方法もありますが、結合条件を間違えると 取りこぼし が起きやすいため、正確性を重視する場合は NOT EXISTS の方が安全です。

1. 基本の書き方

SELECT *
FROM users u
WHERE NOT EXISTS (
SELECT 1
FROM orders o
WHERE o.user_id = u.id
);
ポイント:
サブクエリが 1件でも返ると NOT EXISTS は false。
サブクエリが 0件なら true となり、外側の行が返る。
サブクエリの SELECT 1 の部分は何を返してもよい(値は使わない)。

2. なぜ結合では取りこぼす可能性があるのか

SELECT u.*
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE o.user_id IS NULL;
この方法でも「注文のないユーザー」を取得できます。
しかし 結合条件を複雑にすると、意図した結果が抜けることがある。
例えば複数テーブルを結合すると、条件によっては孤立行が NULL にならず除外される場合があります。
NOT EXISTS はサブクエリ単体で存在確認をするので、複雑な結合でも取りこぼしが起きません。

3. NULL が混ざると NOT IN は危険

SELECT *
FROM users
WHERE id NOT IN (SELECT user_id FROM orders);
orders.user_id に NULL があると、結果が 0件になる ことがあります。
安全性を考えると、NOT EXISTS が推奨です。

4. 実務での使いどころ

注文がないユーザーを抽出する
関連レコードが存在しないデータをチェックする
データ整合性確認の自動化
5. まとめ
NOT EXISTS は 「サブクエリが0件なら true」 の条件で行を抽出できる。
結合による LEFT JOIN + IS NULL は場合によって取りこぼしがある。
NOT IN は NULL に弱い。
よって 正確性を求める場合は NOT EXISTS がベスト。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?