SQLの学習が進むにつれて、多くの人がつまずくのが「サブクエリの多重構造」です。特に応用情報技術者試験やデータベーススペシャリスト試験では、複数のサブクエリが入れ子になったり、FROM句に登場する複雑なSQLが出題され、読み解けずにフリーズしてしまう受験者も少なくありません。
本記事では、「何がどうつながっているのか分からない」という混乱を、段階的に・論理的に・親しみやすく解きほぐすことを目的とします。SQLの全体構造をA to Zで整理し、読み方の順番や視点をCoT(Chain of Thought)的に展開しながら、会話形式でやさしく解説。さらに、実務に通じるような身近な例や図表も使って、「複雑なSQLをシンプルに捉える感覚」を身につけていただけます。
あなたが「サブクエリ恐怖症」から抜け出し、SQL構造の読解力を本質的に高める第一歩を、ここから一緒に踏み出しましょう。
目次
サブクエリ構造の全体像をつかむ│SQLの読み方に「順番」がある
「なんだこのSQL…どこから読めばいいんだ?」
応用情報技術者やデータベーススペシャリストの午後試験では、そんな絶望的な気分になる“入れ子だらけ”のSQL文が登場します。
特に今回のようなSQL文では、以下の特徴があります:
- FROM句にサブクエリが2つ登場
- SELECT句でも別名を利用
- JOIN句がサブクエリ同士をつなぐ
このようなとき、見た目の複雑さに惑わされると「全体がブラックボックス」に感じられ、どこから読んでも意味が取れなくなってしまいます。
まず覚えるべきこと:SQLは「実行順」と「記述順」が違う!
1. FROM(テーブルやサブクエリの定義)
2. JOIN(複数テーブルの結合)
3. WHERE(条件による絞り込み)
4. GROUP BY(グループ化)
5. SELECT(抽出項目の定義)
6. ORDER BY(並び順、あれば)
つまり、SQLは見た目の上からではなく、「実行順」に従って読むべきなのです。
構造の「上」ではなく、「下」から積み上げる
例えば、今回のSQLでは、最初に出てくる SELECT CK.キャンペーン種別, ...
は最後に読む部分です。
真っ先に見るべきなのは、むしろ一番下の「FROM」句の中身です。
FROM 売上 U
INNER JOIN 売上明細 M ON ...
INNER JOIN 商品 S ON ...
この部分が「売上データをどう集めているか」を定義しており、その結果を UK
という名前の中間表にまとめています。
サブクエリは「一時的なテーブル名」として読む
(SELECT ... FROM キャンペーン実施 ... GROUP BY ...) CK
これは「CKという仮のテーブルを用意している」と解釈すると、全体が見通しやすくなります。
表で整理:今回のSQLに出てくるサブクエリ構造
仮名 | サブクエリの中身 | 意味・役割 |
---|---|---|
CK | キャンペーン実施テーブルの集約 | 実施金額を集計した仮テーブル |
UK | 売上・商品・明細を結合した結果 | 売上金額・原価の集計用 |
会話でおさらい
💬 生徒くん:「うわ…SELECTの中にまたSELECTが…どっから読むのこれ?」
👨🏫 先生:「上からじゃなくて、“一番深いFROM句”から見るんだよ。そこが土台だから」
💬 生徒くん:「なるほど!そしたら、UKとかCKって“途中で作った表”ってこと?」
👨🏫 先生:「正解!“一時的な表”をつなげて、最後にSELECTで集めてるんだ」
複雑なSQLを読み解くステップ│図解と具体例で“構造”を見抜く
複雑なSQLを読みこなすには、「手順」と「見立て」が重要です。
ここでは実際の構造を分解して、どのような手順で読めば良いか、図と具体例を交えて説明します。
ステップ1:サブクエリの「中身」を読む前に、出力される列名をチェック!
SELECT CK.キャンペーン種別, COALESCE(UK.売上計, 0) AS 売上計,
COALESCE(UK.原価計, 0) AS 原価計,
COALESCE(UK.売上計, 0) - COALESCE(UK.原価計, 0) AS 粗利益,
CK.キャンペーン実施金額計
まずここで確認したいのは、「このSQLはどんな結果テーブルを出そうとしているのか?」です。
出力列 | 説明 |
---|---|
キャンペーン種別 | 各行の主キー的役割 |
売上計 | UKサブクエリで集計された売上金額 |
原価計 | UKサブクエリで集計された原価合計 |
粗利益 | 売上計 - 原価計(式で算出) |
キャンペーン実施金額計 | CKサブクエリから取得した実施コスト |
ステップ2:FROM句の中の「仮テーブル」を1つずつ確認
FROM
(SELECT キャンペーン種別, SUM(キャンペーン実施金額) AS キャンペーン実施金額計
FROM キャンペーン実施
WHERE キャンペーン番号 = :キャンペーン番号
GROUP BY キャンペーン種別) CK
→ CKは「キャンペーンごとの実施金額集計結果」
(SELECT U.キャンペーン種別,
SUM(M.商品個数 * M.商品単価) AS 売上計,
SUM(M.商品個数 * S.原価) AS 原価計
FROM 売上 U
INNER JOIN 売上明細 M ON U.売上番号 = M.売上番号
INNER JOIN 商品 S ON M.商品番号 = S.商品番号
WHERE U.キャンペーン番号 = :キャンペーン番号
GROUP BY U.キャンペーン種別) UK
→ UKは「売上・原価を商品明細と結合して算出した集計」
ステップ3:JOIN句で仮テーブルを結合していることを確認
ON CK.キャンペーン種別 = UK.キャンペーン種別
同じキャンペーン種別を持つレコードを1行に統合
図解で構造を視覚化
+------------------+
| CK:キャンペーン実施集計 |
| キャンペーン種別,金額計 |
+------------------+
|
| JOIN(キャンペーン種別)
v
+--------------------------+
| UK:売上・原価の集計 |
| キャンペーン種別,売上,原価 |
+--------------------------+
|
v
+-----------------------------------+
| SELECT文で最終出力(粗利など) |
+-----------------------------------+
実生活例で置き換えればこうなる
キャンペーンAで販売した商品をまとめた「売上台帳(UK)」と、
キャンペーンAに使った「広告費や景品費などの出費一覧(CK)」を用意し、
それらを突き合わせて「収支表」を作っているイメージです。
会話でおさらい
💬 生徒くん:「サブクエリの中って、結局なにしてるんだっけ?」
👨🏫 先生:「売上や原価、キャンペーン実施コストをそれぞれ“集計”してるんだよ。しかも、仮テーブルとして」
💬 生徒くん:「それをJOINして、まとめて1行にして、SELECTで見た目を整えてると!」
👨🏫 先生:「そう、それがSQL構文の“流れ”と“構造”!」
親・子・孫テーブルの関係を見抜く│JOIN構造の読み方と“世代感覚”
サブクエリの中に複数のテーブルがJOINされていると、「どのテーブルが主役なのか」「どこから何が引っ張られているのか」が見えづらくなります。
そこで役立つのが、親・子・孫という“世代”のイメージでテーブル関係を読み解く方法です。
典型構造:「親→子→孫」でデータが伝搬する
今回の UK
サブクエリを例にとると、次のように3層のテーブルが関係しています:
FROM 売上 U
INNER JOIN 売上明細 M ON U.売上番号 = M.売上番号
INNER JOIN 商品 S ON M.商品番号 = S.商品番号
図3:親・子・孫テーブル構造
売上(U)──┐
└──▶ 売上明細(M)──▶ 商品(S)
親 子 孫
- 売上(U):キャンペーンごとの購入履歴(親)
- 売上明細(M):売上1件に紐づく複数の購入商品(子)
- 商品(S):商品の価格や原価などのマスタ情報(孫)
“親”テーブルから読み始める
この構造では、「親→子→孫」へとデータが受け渡されているイメージを持つことが大切です。
- ✅ 売上がなければ、売上明細もない
- ✅ 売上明細がなければ、商品との照合もできない
つまり、JOIN構造は「親を起点に、子・孫をたどっていく」という視点で読むと、整理しやすくなります。
JOINの役割は“列情報の補完”
このJOIN構造の目的は、「売上金額」や「原価」を算出するための情報を、子・孫から補っているということです。
取得元 | 列 | 用途 |
---|---|---|
売上明細(M) | 商品番号、個数、単価 | 売上計算の元 |
商品(S) | 原価 | 原価合計の計算用 |
会話でおさらい
💬 生徒くん:「あの、JOINの中って…どのテーブルが主なんですか?」
👨🏫 先生:「売上(U)が主役だね。売上がないと、そもそも明細も商品も意味がないから」
💬 生徒くん:「じゃあ、売上→明細→商品って、親・子・孫みたいな感じ?」
👨🏫 先生:「その通り!それぞれから欲しい情報をJOINで集めてるって考えると、理解しやすいよ」
SQL構文の“入れ子”を見抜く│複数サブクエリを構造で分解する方法
複雑なSQL文の混乱ポイントは、主に「入れ子構造(ネスト)」の見えづらさにあります。
しかし、これはコードとして書かれているだけで、視覚的に分解すれば“階層構造”に過ぎないのです。
ネスト構造を「箱」に置き換えて見てみよう
SQLの各サブクエリは、実は「箱(ブロック)」のようなもので、仮の名前をつけて再利用されているに過ぎません。
FROM
(SELECT ... FROM キャンペーン実施 ...) CK
JOIN
(SELECT ... FROM 売上 ...) UK
→ これは、CKという箱とUKという箱をJOINして、新しい結果を作っている、という構図です。
サブクエリは“表の部品”であり、テーブルと等価
これが重要なポイントです:
✅ サブクエリは「新しいテーブル(仮想表)」を作成している構文です。
つまり、サブクエリとは:
- SELECT文で加工された 一時的なテーブル
- RDB的には ビュー(VIEW)に近い存在
- その場限りの 仮想テーブルとしてJOIN対象に
名前 | 内容 | 役割 |
---|---|---|
CK | キャンペーン実施金額の集約 | 「費用面」の仮テーブル |
UK | 売上・原価の集約 | 「収益面」の仮テーブル |
CK + UK | JOINで統合 | 最終的な収支結果テーブル |
入れ子構造を見抜くコツ:キーワードの直後を探す
SQLで入れ子構造を見抜くには、「次の3つ」に注目すると効果的です:
FROM
直後の(
⇒ サブクエリの始まりSELECT
の中にある(
⇒ 計算目的の入れ子(今回なし)JOIN
の対象が(
で始まる ⇒ サブクエリの結合
FROM (SELECT ...) AS 仮名
JOIN (SELECT ...) AS 仮名
こうしたパターンを見つけると、「あ、これは中に別SQLがあるな」と気づけます。
会話でおさらい
💬 生徒くん:「なんか、サブクエリが“箱の中に箱”みたいで混乱する…」
👨🏫 先生:「まさにその通り。でも、それぞれの箱に“名前”がついてるよね? それがヒントになる」
💬 生徒くん:「つまり、CKとかUKとか、箱の中で定義された表をJOINしてるってことか」
👨🏫 先生:「そう、それだけの話!名前がついた時点で、“1テーブル”として見ていいんだよ」
複雑なサブクエリSQLの読み解き方まとめ│“構造”と“順番”がカギ
午後試験レベルのSQL文は、複数のサブクエリが重なり、JOINが複雑化することで「どこから読めばいいか分からない」状態を生みます。
しかし、今回解説したように、次の3つの視点を持つだけで、頭の中が整理されて読みやすくなります。
✅ 攻略ポイントまとめ
視点 | 内容 |
---|---|
① 実行順で読む | SQLは「SELECT」からでなく、「FROM → JOIN → WHERE → SELECT」の順で処理される |
② 仮想テーブルとして見る | サブクエリは「一時的に作られたテーブル」。中身を分離して捉える |
③ 世代構造で見る | JOINは「親→子→孫」のようなデータの流れを可視化すると理解しやすい |
🔹 サブクエリ構造は「構造×視点」で克服できる!
「サブクエリが出てきたらもうお手上げ…」ではなく、
“読み方の順番”と“構造の見立て”さえ意識すれば、誰でも読み解けるようになります。
午後試験で見かける難解SQLも、いくつかの「意味ある箱」に分けて理解すれば、得点源に変えることも可能です。
会話でおさらい
💬 生徒くん:「あれ?最初は見ただけでフリーズしたけど、今なら読めそうかも…」
👨🏫 先生:「それは“順番”と“構造”で考えたからだよ。SQLも、実は論理的なんだ」