コース一覧
SQL実践:JOIN・サブクエリ・データ更新
WHERE句のサブクエリ

SQL実践:JOIN・サブクエリ・データ更新

JOIN、集合演算、サブクエリ、CTE、DDL・DMLを学び、複数テーブルを組み合わせてデータベースを作成・更新する無料コースです。

1
テーブル結合
01. なぜ結合が必要か5分
02. INNER JOINの基本5分
03. LEFT/RIGHT OUTER JOIN5分
04. 複数テーブルの結合5分
05. 自己結合5分
06. 集合演算 UNION/INTERSECT/EXCEPT5分
07. 結合の実践演習5分
08. テーブル結合クイズ5分
2
サブクエリ活用
01. サブクエリとは5分
02. WHERE句のサブクエリ5分
03. FROM句のサブクエリ5分
04. SELECT句のサブクエリ5分
05. WITH句(CTE)の活用5分
06. サブクエリ実践クイズ5分
3
テーブル作成とデータ操作
01. CREATE DATABASE と CREATE TABLE5分
02. データ型の選び方5分
03. INSERT 文でデータを追加する5分
04. UPDATE 文でデータを更新する5分
05. DELETE 文でデータを削除する5分
06. 物理削除と論理削除5分
07. ALTER TABLE で構造を変更する5分
08. 制約 (NOT NULL / UNIQUE / DEFAULT)5分
09. TRUNCATE と DROP5分
10. DDL / DML 実践クイズ5分

WHERE句のサブクエリ

該当する ID を、手で並べている

employees (社員) と trainings (研修の受講記録) の 2 つのテーブルがあるとします。「研修を修了した社員だけ」を名簿から出したい。まず受講記録から社員 ID を調べます。

SQL クエリ

SELECT DISTINCT employee_id
FROM trainings
WHERE completed_at IS NOT NULL;
-- 3, 7, 12, 18

SELECT id, name FROM employees WHERE id IN (3, 7, 12, 18);

動きますが、この (3, 7, 12, 18) は受講者が 1 人増えるたびに書き直しになります。しかも、書き直し忘れても SQL はエラーを出しません。黙って古い名簿を返すだけです。

括弧の中で、条件になる集合を作る

IN の丸括弧の中には、値を並べる代わりにサブクエリを置けます。

SQL クエリ

SELECT id, name
FROM employees
WHERE id IN (
  SELECT employee_id
  FROM trainings
  WHERE completed_at IS NOT NULL
)
ORDER BY name;

内側が「修了者の社員 ID の一覧」を作り、外側がその一覧に含まれる社員だけを返します。受講記録が増えても減っても、このクエリは直さなくて済みます。

何行返るかで、演算子が決まる

サブクエリを WHERE のどこに書くかより先に、「内側は何行返すのか」を数えてください。ここを間違えると必ず落ちます。

SQL クエリ

-- 内側が 1 行だけ返る  比較演算子が使える
WHERE dept_id = (SELECT id FROM departments WHERE name = '営業')

-- 内側が複数行返る  IN を使う
WHERE dept_id IN (SELECT id FROM departments WHERE floor = 5)

複数行返るサブクエリに = を使うと、実行した瞬間に more than one row returned by a subquery used as an expression で止まります。逆に言えば、このエラーが出たときは「内側が思ったより多く返っている」というサインです。

NOT IN は、NULL が 1 つ混じると全滅する

「研修を 1 度も受けていない社員」を出そうとして NOT IN を使うと、思わぬ結果になることがあります。

SQL クエリ

-- trainings.employee_id に NULL が 1 行でもあると、0 件になる
SELECT id, name
FROM employees
WHERE id NOT IN (SELECT employee_id FROM trainings);

NULL との比較は真でも偽でもなく「不明」になります。すると「どれとも一致しない」と言い切れる行が 1 つも無くなり、全行が条件から外れます。相手の列が NULL を許しているなら、NOT EXISTS に置き換えます。

SQL クエリ

SELECT id, name
FROM employees e
WHERE NOT EXISTS (
  SELECT 1 FROM trainings t WHERE t.employee_id = e.id
);

EXISTS は「内側が 1 行でも返るか」だけを見る書き方で、内側から外側の行 (e.id) を参照しています。こうした書き方を相関サブクエリと呼びます。

テーブル構造

CREATE TABLE customers (
  id INT PRIMARY KEY,
  name VARCHAR(40)
);
CREATE TABLE orders (
  id INT PRIMARY KEY,
  customer_id INT,
  amount INT
);
INSERT INTO customers VALUES
  (1, '佐藤'),
  (2, '鈴木'),
  (3, '田中'),
  (4, '高橋'),
  (5, '伊藤');
INSERT INTO orders VALUES
  (101, 1, 3000),
  (102, 1, 1500),
  (103, 2, 8000),
  (104, 4, 5000);

期待される出力

idname
1佐藤
2鈴木
4高橋

ヒント

サブクエリは SELECT customer_id FROM orders で書ける

複数行を返すので = ではなく IN を使う

並び順は ORDER BY id

このレッスンに出てくる用語

意味があいまいなまま進んだ語は、ここから読み直せます。

  • テーブルDB の表 (Excel のシートみたいなもの)
  • SQLデータベースを操作するための共通言語
  • サブクエリSQL文の中に埋め込まれた別のSQL
  • 演算子//は切り捨て除算(7 // 2 = 3)。
query.sql
学習モード
エディタを読み込んでいます
コードの実行結果
データベースを初期化中...