共通テーブル式 Common Table Expression (CTE) を利用する

ポクルー
質問: SQL中のWITH
SQL文内に WITH [テーブル名] AS( SELECT ....) という記述があるのですが、これは何でしょう?一時テーブルっぽく見えます。

共通テーブル式 Common Table Expression(CTE)について紹介します。

共通テーブル式 - Common Table Expression(CTE)

WITH ~ AS (...) という形で定義される、一時的な名前付きのクエリ結果です。 見た目は一時テーブルに似ていますが、実際にはメモリやtempdbに物理的なテーブルを作成するわけではありません。

CTEの特徴

項目内容
名前一時的なクエリ結果に対して別名(例: Duplicates)をつけられる
対象同一クエリ内でのみ有効(クエリ終了後に消える)
用途ウィンドウ関数の処理、階層構造の展開、読みやすさ向上など
パフォーマンス実体のない「論理的なビュー」として扱われるため、複数回参照すると都度評価されることがある(=複数回呼び出しは注意)
書き換え可能INSERT INTO, UPDATE, DELETE と組み合わせて使える(制限あり)

書式

WITH [CTE名] AS (
 [クエリ]
)
[クエリ]

products テーブル
idmodelnamecategoryprice
1C-XM01モーダンチェアチェア56000
2X-XD05ラージデスクテーブル87000
3A-DA40ラウンドダイニングチェアチェア28000
4O-XX100ナチュラルオフィスチェア13800
5R-D400ラウンドダイニングテーブルテーブル128000
6R7000ウッドキャビネットその他32000


データ挿入のSQL
INSERT INTO products (id, model, name, category, price) VALUES
(1, 'C-XM01', 'モーダンチェア', 'チェア', 56000),
(2, 'X-XD05', 'ラージデスク', 'テーブル', 87000),
(3, 'A-DA40', 'ラウンドダイニングチェア', 'チェア', 28000),
(4, 'O-XX100', 'ナチュラルオフィス', 'チェア', 13800),
(5, 'R-D400', 'ラウンドダイニングテーブル', 'テーブル', 128000),
(6, 'R7000', 'ウッドキャビネット', 'その他', 32000);


上記のテーブルでpriceの平均値より高いpriceの値を持つレコードを列挙する場合の例です。


今回はサブクエリではなく、CTEを利用して実行します。以下のSQLを記述します。
WHERE句でAVG(price)を記述するとエラーになるため、先にpriceの平均値を計算して、CTEに挿入しておき、後半のクエリでCROSS JOINして priceの平均値を参照する動作になります。

WITH Average AS (
SELECT AVG(price) as ap FROM products
)
SELECT productsBV.* FROM products CROSS JOIN Average WHERE price > Average.ap
補足
以下のSQLはエラーになるため、通常はサブクエリを利用します。サブクエリについてはこちらの記事を参照してください。
select id, model, name, category, price FROM products WHERE price > AVG(price)

実行結果

以下の結果となります。

idmodelnamecategoryprice
2X-XD05ラージデスクテーブル87000
5R-D400ラウンドダイニングテーブルテーブル128000

例2: 重複するレコードの削除

こちらの記事を参照してください。


AuthorPortraitAlt
著者
iPentec.com の代表。ハードウェア、サーバー投資、管理などを担当。
Office 365やデータベースの記事なども担当。
作成日: 2014-06-21
Copyright © 1995–2025 iPentec all rights reserverd.