🙄

【PostgreSQL】EXISTS・NOT EXISTSについて

に公開

準備

classes

class_id class_name
1 1年A組
2 1年B組
3 2年A組
4 2年B組

students

student_id student_name class_id
1 田中 太郎 1
2 佐藤 花子 1
3 鈴木 一郎 2
4 山田 次郎 3
CREATE TABLE classes (
    class_id SERIAL PRIMARY KEY,
    class_name VARCHAR(50) NOT NULL
);

CREATE TABLE students (
    student_id SERIAL PRIMARY KEY,
    student_name VARCHAR(100) NOT NULL,
    class_id INT REFERENCES classes(class_id) ON DELETE CASCADE
);

-- クラスの追加
INSERT INTO classes (class_name) VALUES
('1年A組'),
('1年B組'),
('2年A組'),
('2年B組');

-- 生徒の追加
INSERT INTO students (student_name, class_id) VALUES
('田中 太郎', 1), -- 1年A組
('佐藤 花子', 1), -- 1年A組
('鈴木 一郎', 2), -- 1年B組
('山田 次郎', 3); -- 2年A組

-- 2年B組には生徒を登録しない(NOT EXISTS のテスト用)

EXISTSとは

データが存在するかどうかをチェックするSQLのしくみ

  • データが 1行でもあるなら「YES」(=条件が満たされる)
  • 1行もないなら「NO」(=条件が満たされない)

使用例

生徒が1人以上いるクラスを取得(2年B組は除外される)

SELECT * FROM classes c
WHERE EXISTS (
    SELECT * FROM students s 
    WHERE s.class_id = c.class_id
);

処理の流れ

1.メインクエリがclassesテーブルのデータを1行ずつ取得するので、最初の行が取得される

class_id class_name
1 1年A組

2.サブクエリを実行

生徒が1人以上いる→YES

3.上記2.でYESになったので結果に含める

4.classesテーブルの次の行を取得し上記の手順で調べる

class_id class_name
2 1年B組

5.同じようにclassesテーブルのデータを1行ずつ取得しながら調べる
→データがない場合(2年B組)だけ「NO」になる!

class_id class_name サブクエリの結果
1 1年A組 YES✅
2 1年B組 YES✅
3 2年A組 YES✅
4 2年B組 No❌

NOT EXISTSとは

データが存在しないことをチェックするSQLのしくみ

使用例

「生徒がいないクラス」を取得

SELECT * FROM classes c
WHERE NOT EXISTS (
    SELECT * FROM students s 
    WHERE s.class_id = c.class_id
);

<出力例>

処理の流れ

1.メインクエリがclassesテーブルのデータを1行ずつ取得するので、最初の行が取得される

class_id class_name
1 1年A組

2.サブクエリを実行

生徒が1人以上いる→NO(データが存在しない場合YESになる)

3.上記2.で生徒が1人以上いたので結果にこの行は含めない

4.classesテーブルの次の行を取得し同じように調べる

class_id class_name
2 1年B組

5.同じようにclassesテーブルのデータを1行ずつ取得しながら調べる

6.クラスID4のデータを同じように調べた時、生徒が1人もいない→YESなので、結果にこの行を含める

class_id class_name サブクエリの結果
1 1年A組 No❌
2 1年B組 No❌
3 2年A組 No❌
4 2年B組 YES✅

Udemyで講座を公開中!
https://zenn.dev/codek2/articles/e9e44f3e0023fb

X(旧Twitter)
https://twitter.com/kunchan2_

Zenn 本
https://zenn.dev/codek2?tab=books

Youtube
https://www.youtube.com/@codek2_studio

Discussion