VALUESのテーブルって何よ❓

魔クロード(Claude)から発せられた見たこともないSQL文をメモ(SQL Server)。


SELECT
    E.経費ID, COUNT(M.経費ID) 行数
FROM
    (VALUES (101), (102)) E(経費ID)
LEFT JOIN
    経費明細 M ON E.経費ID = M.経費ID AND M.取引NO = 'ABC0123'
GROUP BY
    E.経費ID
	

この構文は テーブル値コンストラクタ(Table Value Constructor) と呼ばれ、一時的なテーブルを作成するのに便利。


構文の仕組み

(VALUES (値1), (値2), ...) エイリアス(列名) という形式で、その場でテーブルを生成できる。

  • VALUES句: データの中身
  • エイリアス: テーブルの別名(必須)
  • 列名: カラム名の指定(省略すると勝手にセットされる)


何が嬉しいのか

従来のIN句では「存在するデータ」しかカウントできない。

SELECT 
    経費ID, COUNT(*) 行数
FROM 
    経費明細
WHERE 
    取引NO='ABC0123' AND 経費ID IN(101,102)
GROUP BY 
    経費ID

これだと、例えば、経費ID=102のデータが0件の場合、結果に現れない。

テーブル値コンストラクタを使えば、0件のデータも含めて集計可能


使用例


  • 複数列のデータを定義

SELECT 
    E.経費ID,
    E.経費名,
    COUNT(M.経費ID) 件数
FROM
    (VALUES 
        (101, '手数料'),
        (102, '保管料')
    ) E(経費ID, 経費名)
LEFT JOIN
    経費明細 M 
ON 
    E.経費ID = M.経費ID
GROUP BY
    E.経費ID, E.経費名
  • マスタデータがない時の簡易集計

SELECT 
    W.番号,W.名前,
    COUNT(B.注文日) 件数
FROM
    (VALUES 
      (1, '日'),
      (2, '月'),
      (3, '火'),
      (4, '水'),
      (5, '木'),
      (6, '金'),
      (7, '土')
    ) W(番号, 名前)
LEFT JOIN
    注文 B 
ON 
    DATEPART(WEEKDAY, B.注文日) = W.番号
    AND B.注文日 >=  '2026-01-01' 
    AND B.注文日 <  '2026-02-01'
GROUP BY
    W.番号,W.名前
ORDER BY
    W.番号

これは2026年1月の曜日ごとの注文件数を集計している。データベースには存在しない曜日テーブルを一時的に作って集計。

DATEPART関数は引数WEEKDAYなら曜日の番号を返す(日本では日曜が1)。


まとめ

  • 一時的なマスタデータを作りたい時に便利
  • 0件も含めた集計が簡単にできる
  • マスタテーブルを作るほどでもないデータに最適


知らなかったSQL、意外と使い道がありそうだ。
それにしても魔クロード👾は神だな。ありがとう。