IPA|情報処理技術者試験

複雑なサブクエリSQLを“構造”で読み解く│午後試験の入れ子JOINを攻略する考え方

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つ」に注目すると効果的です:

  1. FROM 直後の ( ⇒ サブクエリの始まり
  2. SELECT の中にある ( ⇒ 計算目的の入れ子(今回なし)
  3. 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も、実は論理的なんだ」

-IPA|情報処理技術者試験