CodeGym /コース /SQL SELF /FROMでのサブクエリの使い方

FROMでのサブクエリの使い方

SQL SELF
レベル 14 , レッスン 1
使用可能

もっと深くラビットホールに潜ってみよう!今回はFROM構文でサブクエリを使う方法を見ていくよ。これはSQLエンジニアがよく使うテクで、その場で強力な一時テーブルを作って、まるでDBに存在してるかのように再利用できるんだ。

例えば、レポートを作る時に計算やグループ化、データのフィルタリングが必要だけど、サーバーに一時テーブルを作りたくない場合、どうする?そこでFROMのサブクエリが登場!これを使うと:

  • データを一時的にまとめたり、集計したりしてからメインクエリに渡せる。
  • その場で構造化されたデータセットを作れる。
  • DBに余計な中間データを保存せずに、操作回数を減らせる。

FROMのサブクエリは、メインクエリで使えるミニテーブルみたいなもの。モジュールを組み立てる感じで、速くて柔軟、しかも余計なコストもかからないよ :)

FROMサブクエリの基本

FROMサブクエリでは、サブクエリを使って一時テーブル(またはサブテーブル)を作り、それを全体のクエリの一部にするんだ。やることは3つ:

  1. サブクエリをFROM構文の中でカッコで囲んで書く。
  2. サブクエリにエイリアス(別名)をつける。
  3. そのエイリアスを、普通のテーブルみたいに使う。

シンタックス

SELECT カラム
FROM (
    SELECT カラム
    FROM テーブル
    WHERE 条件
) AS エイリアス
WHERE 外部条件;

ちょっと難しそう?じゃあ、例を見てみよう!

例:学生と平均点

例えば、こんな2つのテーブルがあるとする:

students(学生データ — 名前とID):

student_id student_name
1 Alex
2 Anna
3 Dan

grades(学生の成績データ):

grade_id student_id grade
1 1 80
2 1 85
3 2 90
4 3 70
5 3 75

さて、やりたいことは:学生ごとの平均点リストを取得すること。

まずは、各学生の平均点を計算するサブクエリを書いて、それをメインクエリで使ってみよう。

SELECT s.student_name, g.avg_grade
FROM (
    SELECT student_id, AVG(grade) AS avg_grade
    FROM grades
    GROUP BY student_id
) AS g
JOIN students AS s ON s.student_id = g.student_id;

結果:

student_name avg_grade
Alex 82.5
Anna 90.0
Dan 72.5

その場で一時テーブルを作る

FROMのサブクエリは、データ処理を複数段階でやりたい時に特に便利。例えば、平均点だけじゃなくて、各学生の最高点も一緒に計算したい場合、全部1つのクエリでできる!

SELECT g.student_id, g.avg_grade, g.max_grade
FROM (
    SELECT student_id, 
           AVG(grade) AS avg_grade, 
           MAX(grade) AS max_grade
    FROM grades
    GROUP BY student_id
) AS g;

結果:

student_id avg_grade max_grade
1 82.5 85
2 90 90
3 72.5 75

これ、ちゃんとavg_grademax_gradeみたいなカラムを持つ一時テーブルとして動いてるよ。

FROMサブクエリはどんな時に使うといい?

集計データが欲しい時。 まず計算(平均、合計、最大値など)をしてから、他のテーブルと結合したい場合。

データをフィルタしたい時。 メインテーブルと結合する前にデータを絞り込みたい時。

複雑なクエリをシンプルにしたい時。 複雑な処理を段階的に分けると、混乱しにくいよ。

例:2段階処理の学生レポート

例えば、平均点が80より高い学生だけを探したいとしよう。まず平均点を計算するサブクエリを書いて、それをフィルタに使う。

SELECT s.student_name, g.avg_grade
FROM students AS s
JOIN (
    SELECT student_id, AVG(grade) AS avg_grade
    FROM grades
    GROUP BY student_id
) AS g ON s.student_id = g.student_id
WHERE g.avg_grade > 80;

結果:

student_name avg_grade
Alex 82.5
Anna 90.0

使う時のポイントとアドバイス

エイリアスは必須。 サブクエリには必ずエイリアス(例:AS g)をつけよう。じゃないとPostgreSQLはその「一時テーブル」をどう呼べばいいか分からなくなる。

最適化。 FROMサブクエリは、テーブルのJOINより遅くなることがある。特にサブクエリ内でフィルタしてる場合は注意。

インデックス。 結合やフィルタに使うカラムにはインデックスを貼っておこう。パフォーマンスにめっちゃ影響するよ。

複雑なクエリ例:コースごとの学生数

じゃあ、もうちょっとリアルな課題をやってみよう。例えば、こんなテーブルがある:

courses(コース一覧):

course_id course_name
1 SQL Basics
2 Python Basics

そしてenrollments(学生のコース登録データ):

student_id course_id
1 1
1 2
2 1

さて、各コースに何人の学生が登録しているか知りたい。

SELECT c.course_name, e.students_count
FROM courses AS c
JOIN (
    SELECT course_id, COUNT(student_id) AS students_count
    FROM enrollments
    GROUP BY course_id
) AS e ON c.course_id = e.course_id;

結果:

course_name students_count
SQL Basics 2
Python Basics 1

このレクチャー、気に入ってくれたら嬉しいな…次回はもっと面白い内容になるよ :)

コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION