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

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分

SELECT句のサブクエリ

一覧の隣に、あと 1 列だけ足したい

社員一覧を出しながら、その横に「社内で一番高い年収」も並べておきたい、という注文が来たとします。結合する相手のテーブルはありません。欲しいのは 1 つの値だけで、それを全行に付けたいだけです。

こういうときは、SELECT に並べる列の位置に、そのまま丸括弧の SELECT を置けます。

SQL クエリ

SELECT
  name,
  salary,
  (SELECT MAX(salary) FROM employees) AS top_salary
FROM employees
ORDER BY salary DESC;

top_salary の列には、全行に同じ値が入ります。ここに置けるのは 1 行 1 列だけの値で、これをスカラー値と呼びます。AS で名前を付けるのを忘れると、列見出しがサブクエリの文面そのものになって読めなくなります。

行ごとに違う値を入れる

丸括弧の中から、外側の行を参照することもできます。こうすると、行ごとに違う値が入ります。

SQL クエリ

SELECT
  e.name,
  (SELECT COUNT(*) FROM trainings t WHERE t.employee_id = e.id) AS training_count
FROM employees e
ORDER BY e.id;

t.employee_id = e.id の部分が、今処理している外側の 1 行と内側を結び付けています。これが相関サブクエリです。外側の行の数だけ内側が動くので、数万行を返すクエリでは LEFT JOIN と GROUP BY に書き換えたほうが速いことが多い、とだけ覚えておいてください。

2 行返った瞬間に落ちる

スカラーサブクエリは、名前のとおり 1 行 1 列しか返せません。条件の書き方によって 2 行以上返る可能性があると、その行に当たった瞬間にエラーで止まります。

SQL クエリ

-- 落ちる  部署に 2 人以上いれば 2 行返ってしまう
SELECT
  d.name,
  (SELECT e.name FROM employees e WHERE e.dept_id = d.id) AS member
FROM departments d;

-- 通る  集計で 1 行に畳んでから返す
SELECT
  d.name,
  (SELECT MAX(e.salary) FROM employees e WHERE e.dept_id = d.id) AS top_salary
FROM departments d;

厄介なのは、データが少ないうちは通ってしまうことです。「開発中は動いていたのに、本番でだけ落ちる」の典型がこれなので、書いた時点で「この内側は絶対に 1 行か」を確かめてください。1 行だと言い切れないなら、MAX や SUM などの集計関数で畳むか、LIMIT 1 で明示的に 1 行にします。

テーブル構造

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, '高橋');
INSERT INTO orders VALUES
  (101, 1, 3000),
  (102, 1, 1500),
  (103, 2, 8000),
  (104, 4, 5000),
  (105, 4, 2500);

期待される出力

idnametotal_amount
1佐藤4500
2鈴木8000
3田中0
4高橋7500

ヒント

SELECT 句に (SELECT SUM(amount) FROM orders WHERE ...) と書く

注文がない顧客は SUM が NULL になるので COALESCE で 0 にする

サブクエリの中で o.customer_id = c.id と相関させる

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

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

  • テーブルDB の表 (Excel のシートみたいなもの)
  • サブクエリSQL文の中に埋め込まれた別のSQL
  • 処理計算や代入を表す長方形
  • 関数処理に名前を付けて再利用できる単位
query.sql
学習モード
エディタを読み込んでいます
コードの実行結果
データベースを初期化中...