📖 テーマ設定
🔊 音声設定
1.2
1.0
1.0
▶️ 再生コントロール
🎵 BGM設定
0.3
🔔 効果音設定
0.3

サブクエリ・ビュー演習

概要

  • 日程: Day 2 / セッション 8
  • 時間: 14:00-14:30
  • 形式: 実習
  • ゴール: 「平均給与より高い社員」のクエリと、よく使う集計を呼び出せるビュー1つを作成できる
  • 学習形式: ハンズオン実習(AIペアプログラミング)

導入(5分)

前のセッションで「サブクエリは値・表・真偽の3つを返す道具」「ビューは名前付きのSELECT」と整理しました。ここからは実際に手を動かします。

これは、いわばスポーツでフォームを教わった後の素振りの時間です。座学で頭に入れた構文は、自分の手で打ち込んで初めて身につきます。エラーが出たら大歓迎、AIに聞きながらどんどん試してみましょう。

ターミナルで psql に接続して始めます。

docker exec -it postgres-sandbox psql -U postgres -d sandbox

実習・演習(20分)

課題1: スカラーサブクエリで「平均より高い社員」

全社員の平均給与より給与が高い社員を、姓・名・給与を表示してください。

ヒント

  • 平均給与は SELECT AVG(salary) FROM employees; で出る
  • それを WHERE 句に ( ) で埋め込む

解答例

SELECT last_name, first_name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees)
ORDER BY salary DESC;

実行したら、結果の件数と「平均給与より上の人」の名前を1〜2人記憶しておくと、後で検算しやすいです。

課題2: EXISTSサブクエリで「注文がある顧客」

注文を1件以上している顧客の customer_name だけを取り出してください。

ヒント

  • EXISTS (SELECT 1 FROM orders WHERE ...) を使う
  • 外側の customers と内側の orderscustomer_id で対応させる(相関サブクエリ)

解答例

SELECT customer_name
FROM customers c
WHERE EXISTS (
    SELECT 1 FROM orders o WHERE o.customer_id = c.customer_id
)
ORDER BY customer_name;

比較してみよう

同じ結果をJOINでも書けます。書いて結果を比べてみましょう。

SELECT DISTINCT c.customer_name
FROM customers c
JOIN orders o ON o.customer_id = c.customer_id
ORDER BY c.customer_name;

「件数は同じ?」「どちらが読みやすい?」をAIと議論してみてください。

課題3: 部署別平均給与ビューを作る

部署名と平均給与、所属人数を返すビュー v_dept_avg_salary を作成し、平均給与の降順で表示してください。

ヒント

  • CREATE VIEW ビュー名 AS SELECT ...; の形
  • departmentsemployeesdepartment_id でJOIN
  • GROUP BY は部署名で

解答例

CREATE VIEW v_dept_avg_salary AS
SELECT
    d.department_name,
    AVG(e.salary) AS avg_salary,
    COUNT(*) AS member_count
FROM employees e
JOIN departments d ON e.department_id = d.department_id
GROUP BY d.department_name;

SELECT * FROM v_dept_avg_salary ORDER BY avg_salary DESC;

作り直したいときは DROP VIEW v_dept_avg_salary; で消してから再作成できます。

課題4(チャレンジ): インラインビューで「平均以上の部署」

各部署の平均給与を出して、その中で「全社員平均」よりも高い部署だけを表示してください。

解答例

SELECT department_name, avg_salary
FROM (
    SELECT d.department_name, AVG(e.salary) AS avg_salary
    FROM employees e
    JOIN departments d ON e.department_id = d.department_id
    GROUP BY d.department_name
) AS dept_avg
WHERE avg_salary > (SELECT AVG(salary) FROM employees)
ORDER BY avg_salary DESC;

スカラーサブクエリとインラインビューが1つの文の中に同居しています。「カッコの中から先に読む」を意識すると流れがつかめます。

成果物

  • 課題1〜3のSQLと実行結果(4はチャレンジ)
  • 作成したビュー v_dept_avg_salary
  • 「サブクエリで書く/JOINで書く/ビューにする」の使い分けを、自分の言葉で2〜3行メモ

まとめ(5分)

サブクエリは「カッコの中身が値か表か真偽か」を意識すると迷いません。ビューは作るのも壊すのも簡単で、よく使う集計に名前を付けておくだけで、後の自分や同僚が助かります。

エラーで詰まったら遠慮なくAIに「このSQLを実行したらこういうエラーが出た。理由と直し方を教えて」と聞いてみてください。エラー文を貼るのが一番早いコツです。

🔄 振り返りチェック

  • 課題1のクエリを、明日見ても自分で再現できますか?
  • ビューを DROP して作り直す手順は説明できますか?
  • 「JOINでもサブクエリでも書ける」場合、自分はどちらを選ぶかの基準を持てましたか?

補足資料

  • 発展課題: 「注文金額が10万円以上の注文」を返すビュー v_high_value_orders を作る。さらにそれを使って「高額注文を出した顧客の社名一覧」を取り出してみる

学習ガイド

想定される質問と回答例

質問 ヒント
ビューはどこに保存される? データベース内に定義(メタデータ)として保存される。\dv でビュー一覧を見られる
ビューを作る権限はだれにある? sandbox 環境では postgres ユーザーで全権限あり。実務ではDBA(管理者)から付与される
同じ名前のビューを作り直したい CREATE OR REPLACE VIEW v_xxx AS SELECT ... でも書き直せる。列構成が変わる場合は DROP してから
EXISTSとINはどっちが速い? データ量や統計次第で逆転する。最初は「読みやすさ」で選び、遅くて困ったら EXPLAIN で確認

つまずきやすいポイント

つまずきポイント ヒント
column "xxx" must appear in the GROUP BY clause 集計列以外は全部 GROUP BY に入れる必要がある(PostgreSQLの仕様)
インラインビューに AS を付け忘れる FROMの中のサブクエリには必ずエイリアス(AS xxx)を付ける
ビューが更新できないエラー 普通のビューは原則 SELECT 専用。更新したい場合は元テーブルに対して直接INSERT/UPDATE
読み上げを開始します...

AIに質問する