PostgreSQL サブクエリ完全ガイド!SQL初心者でも「副問合せ」がわかる入門解説
生徒
「SQLの勉強を始めたのですが、『サブクエリ』という言葉が出てきて混乱しています。何だか難しそうです……。」
先生
「サブクエリは日本語で『副問合せ』とも呼びます。簡単に言うと、一つの命令文の中にもう一つの命令文が隠れている状態のことです。マトリョーシカのような構造をイメージすると分かりやすいですよ。」
生徒
「命令の中に命令があるんですか?どんな時に使うのでしょうか?」
先生
「例えば『テストの平均点より高い人を探したい』という時です。まず『平均点』を計算して、その結果を使って『高い人』を探しますよね。この二つのステップを一度にやってしまうのがサブクエリの役割です。」
1. サブクエリとは何か?データベース操作の強力な武器
SQLの世界において、**サブクエリ(Subquery)**は非常に便利な機能です。日本語では「副問合せ」と呼ばれます。 通常のSQLは「この表からデータを出して」という一つの指示ですが、サブクエリを使うと「**別の計算で出した結果を使って、この表からデータを出して**」という、より複雑で高度な指示ができるようになります。
プログラミング未経験の方にとって「クエリ」という言葉は馴染みが薄いかもしれませんが、これは単に「データベースへのお願い(命令)」のことです。 サブクエリは、メインの命令(主問合せ)を助けるための、小さな「部品としての命令」だと考えてください。
2. なぜサブクエリが必要なのか?身近な例で解説
例えば、あなたが学校の先生だとしましょう。手元にはクラス全員のテストの点数が書かれた名簿があります。 ここで「**クラスの平均点よりも高い点数を取った生徒だけを抜き出したい**」と思ったとき、あなたならどうしますか?
- まず、全員の合計点を出して、人数で割って「平均点」を計算します。
- その平均点が例えば「75点」だとわかったら、次に名簿を見て「75点より高い人」を探します。
このように、私たちは無意識に二つのステップを踏んでいます。しかし、データベースに対して「平均点より高い人を教えて」と一度に頼みたい場合、最初から「75」という数字が分かっているわけではありません。 そこで、「平均点を計算する」という命令を、メインの命令の中に組み込むのです。これがサブクエリの基本的な考え方です。
3. 【実践例1】比較演算子を使った基本的なサブクエリ
それでは、実際にPostgreSQLで使えるSQLを書いてみましょう。まずは「平均より高い価格の商品」を探す例です。 ここでは「products」という名前の商品テーブルを使います。
実行前のテーブル:products
id | name | price
---+------------+-------
1 | リンゴ | 150
2 | バナナ | 100
3 | メロン | 800
4 | イチゴ | 500
5 | ミカン | 120
6 | ブドウ | 600
このテーブルから、全体の平均価格より高い商品だけを抽出します。 括弧 `()` で囲まれた部分がサブクエリです。
SELECT name, price
FROM products
WHERE price > (
SELECT AVG(price)
FROM products
);
ここで使われている用語を解説します。
- SELECT(セレクト):データを取り出す命令です。
- AVG(アベレージ):平均値を計算する関数です。
- WHERE(ウェア):条件を指定して絞り込むための言葉です。
実行結果:
name | price
-------+-------
メロン | 800
イチゴ | 500
ブドウ | 600
平均価格(378.33...円)より高い商品だけがしっかりと表示されました。 括弧の中の `SELECT AVG(price) FROM products` が先に動いて、平均値を計算してくれているのです。
4. 【実践例2】IN句を使って「リスト」の中から探す
次に、別のテーブルにある情報を使ってデータを絞り込む方法を紹介します。 例えば、「注文があった商品だけを表示したい」という場合です。 ここでは「注文リスト(orders)」テーブルに名前がある商品だけを「商品名簿(items)」から探します。
実行前のテーブル:items(全ての商品)
id | item_name | category
---+-----------+----------
1 | ノート | 文房具
2 | 消しゴム | 文房具
3 | 鉛筆 | 文房具
4 | 定規 | 文房具
5 | コンパス | 文房具
実行前のテーブル:orders(注文された商品ID)
order_id | item_id
---------+---------
101 | 1
102 | 3
103 | 1
注文があった商品の名前だけを知りたいとき、次のように書きます。 `IN` という言葉は、「(リストの中)に含まれている」という意味です。
SELECT item_name
FROM items
WHERE id IN (
SELECT item_id
FROM orders
);
実行結果:
item_name
-----------
ノート
鉛筆
サブクエリが「注文リストにあるID(1と3)」を導き出し、それを元にメインの命令が商品名を表示しました。 これなら、たとえ注文が100万件あっても、自動的に一致する商品だけを探し出してくれます。
5. サブクエリを使う際の注意点:パソコンへの負担
サブクエリはとても便利ですが、使うときには少しだけ注意が必要です。 それは「**パソコン(サーバー)の処理が重くなることがある**」という点です。
サブクエリは、メインの命令が実行されるたびに、中のサブクエリも動くことがあります。 これを「相関サブクエリ」と呼びますが、データの数が膨大(何千万件など)になると、計算に時間がかかってしまい、画面の表示が遅くなる原因になることがあります。
初心者のうちはあまり気にしすぎなくても大丈夫ですが、「サブクエリを使わずに『結合(JOIN)』という別の方法で書けないかな?」と考えることが、脱・初心者の第一歩になります。
6. 【実践例3】最新の日付データを取得する応用
最後に、よく実務でも使われる「最新のデータだけを取り出す」方法を学びましょう。 例えば、ログイン履歴テーブルから、各ユーザーの「一番新しいログイン時間」を調べるようなケースです。
実行前のテーブル:logins
user_id | login_date
--------+------------
1 | 2025-01-01
2 | 2025-01-02
1 | 2025-01-05
3 | 2025-01-03
2 | 2025-01-06
ここでは「MAX」という最高値を出す関数を使って、最新の日付をサブクエリで取得します。
SELECT user_id, login_date
FROM logins
WHERE login_date = (
SELECT MAX(login_date)
FROM logins
);
実行結果:
user_id | login_date
--------+------------
2 | 2025-01-06
このクエリは、「全データの中で、一番新しい日付は何日?」とサブクエリで聞き出し、その日付に一致する行を抜き出しています。 このように、サブクエリは特定の条件(最大値、最小値、合計値など)に合致するデータを探す際に非常に強力なツールとなります。
7. データベースを学ぶ上でのコツ
サブクエリをマスターするためには、まず「自分が手作業で名簿を整理するならどう動くか?」を想像してみるのが一番の近道です。 いきなり難しい英語のコードを書こうとせず、まずは日本語で「〇〇の平均を出して、それより大きいものを探す」という手順を書き出してみましょう。
PostgreSQLは、世界中で使われている非常に安定したデータベースシステムです。 今回学んだサブクエリは、PostgreSQLだけでなく、MySQLやOracleといった他のデータベースでも同じように使えます。 一度覚えてしまえば、エンジニアとしてのスキルが大きく向上しますよ。
一歩ずつ進んでいきましょう。最初はエラーが出ても大丈夫です。 「括弧の閉じ忘れはないか?」「テーブルの名前は合っているか?」を確認する作業も、立派な学習の一部です。 コツコツと練習を積み重ねることで、複雑なデータの抽出も自由自在にできるようになります。