インラインビューとは?SQLの基本例とサブクエリ・CTE・ビューの違い

インラインビューはサブクエリの一種で、FROM句の中に置いたSELECT結果を外側から表のように参照します。 集計後の値で絞り込む、計算した列を別の段階で使う、といった処理を読みやすく分けられます。CREATE VIEWで保存するビューや一時テーブルとは異なり、インラインビューを書いただけで別クエリから使える保存物は作られません。

目次

インラインビューとは

インラインビューは、FROM句の中のサブクエリです。外側のクエリは、そのSELECTが出力する列を表の列のように参照します。Oracleの公式定義はこの形式をinline viewと呼び、MySQLやPostgreSQLではderived table(派生テーブル)として説明されます。

以降のSQL例はMySQL 8.4を前提にしています。DATE_FORMAT、EXPLAIN、ウィンドウ関数、日付の解釈は、他のDBMSではそのまま使えない場合があります。表と列は説明用なので、実際のスキーマに合わせてください。

書き方名前を参照する範囲主な役割
インラインビュー/派生テーブルそのSQL文の外側のクエリFROM内の結果を表として参照
サブクエリ含まれるSQL文の該当位置IN・EXISTS・スカラー・FROM等の総称
CTE(WITH)定義に続く同じSQL文名前付きの結果を読みやすく分割
保存ビュー(CREATE VIEW)権限等に従い他のSQL文からも参照クエリ定義をDBオブジェクトとして保存

別名は省略せず、(SELECT ... ) AS vの形を基本にします。PostgreSQL 17の説明は別名の省略を認めますが、他システムへの移植を考えて書くことを勧めています。DBMSや版ごとの構文を混同しないでください。

インラインビューの基本的な使い方

インラインビューの基本的な使い方は、FROM句内でサブクエリを定義し、それをテーブルのように参照することです。例えば、以下のようなSQLクエリでインラインビューを使用できます。

SELECT v.customer_id, v.total_amount
FROM (
    SELECT customer_id, SUM(amount) AS total_amount
    FROM orders
    GROUP BY customer_id
) AS v
WHERE v.total_amount > 1000;

この例では、インラインビューvを利用して、特定の条件を満たす顧客の合計金額を抽出しています。

基本例の入力と結果を追う

ordersに次の3行があるとします。内側では顧客ごとに合計し、外側では合計が1000を超える顧客だけを残します。単一注文のamountが1000を超えるかどうかを調べる条件とは意味が異なります。

customer_idamount
1600
1500
2800
内側のcustomer_id内側のtotal_amount外側の条件 > 1000
11100残る
2800除外

外側の結果はcustomer_id=1、total_amount=1100の一行です。集計だけで足りるなら、同じ条件をGROUP BYに続くHAVING SUM(amount) > 1000で書く方法もあります。インラインビューを使うと、計算済み列に付けた名前を外側で参照できます。

インラインビューのメリット

インラインビューを使用することで得られる主なメリットは以下の通りです。

クエリの簡潔化

複雑なクエリを簡潔に記述でき、可読性が向上します。

一時的な結果セットの利用

同じSQL文の外側で、内側の結果に付けた別名を参照できます。その文が終わった後に、別のSQL文から同じインラインビュー名を再利用できるという意味ではありません。

データのフィルタリングと集計

集計前の条件と集計後の条件を分けて表現できます。記述が読みやすくなることと、実行時間が短くなることは別なので、性能は実行計画と同じデータで確認します。

コードの再利用性向上

一つのSQL文の中で処理の意図をまとめるのに役立ちます。同じ文で複数回参照したい場合はCTE、複数のSQL文で定義を共有したい場合は保存ビューなどを検討します。

インラインビューとサブクエリの違い

サブクエリという大きなくくりの中に、FROM句で使うインラインビューが含まれます。違いを考えるときは、含める句と必要な結果の形を確認します。

インラインビュー

インラインビューはFROM句で使用するサブクエリであり、サブクエリと対立する種類ではありません。括弧の外に別名を付け、外側から参照する計算列にも名前を付けると、どの列を使うか明確になります。

サブクエリ

サブクエリは他のSQL文に含まれるクエリの総称です。FROMのインラインビューのほか、INで値の集合を調べる形式、EXISTSで存在を調べる形式、単一値を返すスカラーサブクエリなどがあります。返す行・列の数は使う位置と演算子によって異なり、サブクエリ全体がインラインビューより用途の狭い機能という説明は適切ではありません。

例えば、サブクエリは以下のように使用されます:

SELECT customer_id, name
FROM customers
WHERE customer_id IN (
    SELECT customer_id
    FROM orders
    WHERE amount > 1000
);

この例では、サブクエリを使って特定の条件を満たす顧客IDを取得し、その顧客の情報をメインクエリで抽出しています。

インラインビューの実践例

インラインビューは、実際の業務で多様なシナリオに活用できます。以下に、売上データを集計し特定の条件でフィルタリングする例を示します。

売上データの集計とフィルタリング

次のSQLクエリは、各製品カテゴリの総売上を集計し、売上が100,000円以上のカテゴリのみを抽出します。

SELECT category, total_sales
FROM (
    SELECT category, SUM(sales_amount) AS total_sales
    FROM sales
    GROUP BY category
) AS sales_summary
WHERE total_sales >= 100000;

このクエリでは、sales_summaryという別名で集計結果を外側から参照し、合計値でフィルタリングします。これはSQL文内の論理的な分割であり、必ず一時テーブルへ保存されるという意味ではありません。

特定の月の売上ランキング

次の例は、特定の月における売上ランキングを表示するものです。

SELECT product_id, monthly_sales, RANK() OVER (ORDER BY monthly_sales DESC) AS sales_rank
FROM (
    SELECT product_id, SUM(sales_amount) AS monthly_sales
    FROM sales
    WHERE sales_date >= '2024-01-01'
      AND sales_date < '2024-02-01'
    GROUP BY product_id
) AS monthly_sales_data
ORDER BY monthly_sales DESC, product_id;

sales_dateが時刻を含む列でも1月31日全体を含めるため、月初以上・翌月初未満の半開区間を使います。RANKの同額順位は同じですが、結果の表示順は最後のORDER BYで指定します。ウィンドウ内のORDER BYだけで最終表示順を保証しません。

このクエリでは、インラインビューmonthly_sales_dataを用いて特定の月の売上データを集計し、その結果に対してランキングを計算しています。インラインビューを使うことで、集計とランキングを一つのクエリで効率的に処理しています。

インラインビューを使用したデータの集計

インラインビューは、複雑なデータの集計を簡単に行うための強力なツールです。以下に、複数の集計を一つのクエリで行う方法を示します。

複数の集計を一つのクエリで実行

次のSQLクエリは、各店舗の月別売上と平均売上を同時に計算し、結果を店舗ごとに表示します。

SELECT store_id, month, total_sales, avg_sales
FROM (
    SELECT store_id, 
           DATE_FORMAT(sales_date, '%Y-%m') AS month, 
           SUM(sales_amount) AS total_sales, 
           AVG(sales_amount) AS avg_sales
    FROM sales
    GROUP BY store_id, month
) AS store_sales_summary;

このクエリでは、インラインビューstore_sales_summaryを利用して、各店舗の月別売上合計と平均売上を集計し、その結果セットをメインクエリで参照しています。

インラインビューによる累積売上の計算

次の例では、各商品の累積売上を計算し、累積売上が特定の閾値を超えた商品のみを抽出します。

SELECT product_id, cumulative_sales
FROM (
    SELECT product_id, 
           SUM(sales_amount) OVER (
               PARTITION BY product_id
               ORDER BY sales_date, sales_id
               ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
           ) AS cumulative_sales
    FROM sales
) AS cumulative_sales_data
WHERE cumulative_sales > 50000;

この累積例ではsales_idを一意の売上行IDとして追加し、同じ時刻の行も一行ずつ加算する順序を決めています。ROWSとRANGEの公式説明のとおり、同じ並び値の行をまとめる既定のフレームと、一行ずつ加算するフレームでは結果が変わります。実表にsales_idがなければ、一意の並びを決める列へ置き換えてください。同じ商品の複数の売上行が閾値を超えれば、外側にもその商品が複数行出ます。商品ごとの最終合計だけを一行で出したい場合は、GROUP BYで合計する例を選んでください。

このクエリでは、インラインビューcumulative_sales_dataを使って、各商品の累積売上を計算し、その結果から累積売上が50,000円を超えた商品を抽出しています。インラインビューを用いることで、複雑な累積計算もシンプルに記述できます。

インラインビューのパフォーマンス最適化

インラインビューを効率的に使用するためには、パフォーマンスの最適化が重要です。以下に、インラインビューのパフォーマンスを向上させるためのいくつかの方法を紹介します。

インデックスの活用

元のテーブルの検索条件や結合条件に合うインデックスを検討します。ただし、インデックス追加で必ず速くなるとは限らず、更新コストも増えます。まず実行計画と対象件数を確認して、必要な列と列順を選びます。

不要なデータのフィルタリング

インラインビューの中で必要なデータだけを抽出するようにし、不要なデータをフィルタリングすることで、クエリのパフォーマンスを向上させることができます。これは、インラインビュー内のWHERE句やHAVING句を適切に使用することで実現できます。

適切な集計関数の選択

集計関数を使用する際には、パフォーマンスに影響を与えることがあります。必要に応じて、適切な集計関数を選択し、パフォーマンスを考慮して使用しましょう。

クエリプランの確認と最適化

実行計画で、読み取る行数、結合、集計や一時領域などを確認します。次のEXPLAIN例はMySQLを前提とします。実行計画の構文や出力はDBMSによって異なります。

MySQL 8.4の公式説明では、派生テーブルは外側にマージされる場合と内部一時テーブルへ実体化される場合があります。インラインビューの形だけを見て、内側が必ず先に実行・保存されるとは判断できません。

EXPLAIN SELECT category, total_sales
FROM (
    SELECT category, SUM(sales_amount) AS total_sales
    FROM sales
    GROUP BY category
) AS sales_summary
WHERE total_sales >= 100000;

結合の最適化

インラインビューで複数のテーブルを結合する場合、結合順序や結合条件を最適化することで、パフォーマンスを向上させることができます。インラインビュー内で不要な結合を避け、効率的な結合順序を選択しましょう。

インラインビューの使用を控える場合

同じSQL文の中で名前付きの結果を複数箇所から参照したい場合は、WITH句のCTEで意図を整理できます。ただし「CTEなら一度保存して速くなる」とは限りません。SQL Serverの説明ではCTEの結果は実体化されず、外側からの参照で定義クエリが再実行されるとされています。DBMSごとの実行計画を比較してください。

WITH sales_summary AS (
    SELECT category, SUM(sales_amount) AS total_sales
    FROM sales
    GROUP BY category
)
SELECT category, total_sales
FROM sales_summary
WHERE total_sales >= 100000;

最適化では、変更前後で結果が同じか、同じ件数・条件で実行時間がどう変わるかを確認します。集計前と後で条件を動かすと意味が変わる場合があるので、速さより先に結果の正しさを照合します。

公式資料

まとめ

インラインビューは、FROM句内のサブクエリを外側から表として使う書き方です。まず別名と出力列をそろえ、集計前・集計後の条件を分けます。CTEや保存ビューとの使い分けは名前を使う範囲で考え、速度や物理的な保存はDBMSの実行計画で確認してください。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次