一人アドカレ
| 日 | ポスト |
|---|---|
| 1 | 一時テーブルが存在していたら削除する |
| 2 | 何度も使う中間テーブルに名前をつけてクエリを見やすくする |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
| 20 | |
| 21 | |
| 22 | |
| 23 | |
| 24 | |
| 25 |
何度も使う中間テーブルに名前をつけてクエリを見やすくする
この記事は自身のブログを書き直したものです。
課題
クエリを書いていると、何度も同じ中間テーブルを書いている時がある。自分の場合、テーブル結合を幾つかしている時に多い。
同じ中間テーブルのクエリを何度も書いているとミスの元だし、修正するにも手間だし見難いしで大変なので、共通テーブル式を使い見やすくする。
準備
実行環境
- SQL Server 2017 Standard
- 2008 R2 Express, 2012 Standardでも確認済み
- Management Studio 2017
サンプルデータ
fruitsテーブル
| ID | Name | Price |
|---|---|---|
| 1 | apple | 100 |
| 2 | apple | 120 |
| 3 | orange | 50 |
| 4 | orange | 40 |
| 5 | apple | 80 |
| 6 | orange | 60 |
| 7 | banana | 120 |
| 8 | banana | 150 |
解法
共通テーブル式とは名前をつけた中間テーブルのこと。WITH句を使うことで実現できる。
WITH [commonTableName] AS (
SELECT [hoge] AS [column1]
, [fuga] AS [column2]
FROM [someTbl]
WHERE [someCol] = 'piyo' )
SELECT [column1]
, [column2]
FROM [commonTableName]
WITH句からはじまり、WITHの後には共通テーブルの名前[commonTableName]が続く。
その後の括弧内のSELECT文は共通テーブルの定義になり、このSELECT文の結果が共通テーブルとなる。
括弧の後のSELECT文から共通テーブルが使用可能となる。
共通テーブルの特徴として、自己参照が可能で再帰クエリが書ける点がある。
fruitsサンプルテーブルを使った共通テーブルの例が以下。
共通テーブル式に果物ごとの最安値を抽出する文を指定して、SELECT文で各レコードごとに一致する果物の値段と最安値の差額を抽出した。
WITH [commonTable] AS (
SELECT [Name]
, MIN( [Price] ) AS [minPrice]
FROM [fruits]
GROUP BY [Name] )
SELECT [fruits].[ID]
, [fruits].[Name]
, [fruits].[Price] - [commonTable].[minPrice] AS [diffPrice]
FROM [fruits]
INNER JOIN [commonTable]
ON [commonTable].[Name] = [fruits].[Name]
ORDER BY [ID];
| ID | Name | diffPrice |
|---|---|---|
| 1 | apple | 20 |
| 2 | apple | 40 |
| 3 | orange | 10 |
| 4 | orange | 0 |
| 5 | apple | 0 |
| 6 | orange | 20 |
| 7 | banana | 30 |
| 8 | banana | 60 |
| 9 | cherry | 0 |
| 10 | cherry | 100 |
| 11 | pineapple | 0 |
| 12 | pineapple | 30 |
| 13 | banana | 0 |
感想
この例だとぜんぜん共通テーブル式の便利なところが伝わらないかな。。。
同じクエリを何回も書くような時使うと、すっきりして見やすいクエリになります。
再帰クエリも便利だし記録しておきたい。
共通テーブルは中間テーブルである、というと一時テーブルとの違いがわからないので別途記事を書きたい。
⇒『共通テーブル式と一時テーブルの参照可能な範囲の違い』を書きました。