「駑馬十駕」を信念に IT系情報を中心に調べた事をコツコツ綴っています。

SQLを使ってデータを扱うとき、表の形を「横持ち」や「縦持ち」に変換したい場面は多々あります。
例えば、月ごとの売上を列ごとに並べたい、あるいはアンケート結果を1列にまとめたいなど。

こうした「表の回転」に便利なのが PIVOTUNPIVOT です。
本記事では、それぞれの使い方と、主要なDBMSごとの違いを整理します。


PIVOTとは?

PIVOTは 縦持ちデータを横持ちに変換する 機能です。
例:月ごとの売上を集計して列化する。

サンプルデータ
商品売上
A1月100
A2月150
B1月200
B2月180

PIVOTのイメージ

商品1月売上2月売上
A100150
B200180


UNPIVOTとは?

UNPIVOTは 横持ちデータを縦持ちに変換する 機能です。
例:上記の「商品×月売上表」を再び「商品・月・売上」の縦持ちに戻す。


各DBMSでの書き方比較

1. SQL Server

SQL Serverはネイティブで PIVOT / UNPIVOT をサポート。

 
-- PIVOT
SELECT 商品, [1月] AS 売上1月, [2月] AS 売上2月
FROM (
  SELECT 商品, 月, 売上
  FROM Sales
) AS src
PIVOT (
  SUM(売上) FOR 月 IN ([1月], [2月])
) AS pvt;

-- UNPIVOT
SELECT 商品, 月, 売上
FROM SalesPivot
UNPIVOT (
  売上 FOR 月 IN ([1月売上], [2月売上])
) AS unpvt;

2. Oracle

Oracleは PIVOT / UNPIVOT が標準で利用可能。

-- PIVOT
SELECT *
FROM Sales
PIVOT (
  SUM(売上) FOR 月 IN ('1月' AS "売上1月", '2月' AS "売上2月")
);
-- UNPIVOT
SELECT 商品, 月, 売上
FROM SalesPivot
UNPIVOT (
  売上 FOR 月 IN (売上1月 AS '1月', 売上2月 AS '2月')
);

3. PostgreSQL

PostgreSQLはPIVOT句を持たないため、crosstab関数(tablefunc拡張) を使う。

-- PIVOT (crosstab)
SELECT *
FROM crosstab(
  'SELECT 商品, 月, 売上 FROM sales ORDER BY 1,2',
  'SELECT DISTINCT 月 FROM sales ORDER BY 1'
) AS ct(商品 text, "1月" int, "2月" int);
-- UNPIVOTは UNION ALL で対応
SELECT 商品, '1月' AS 月, 売上1月 AS 売上 FROM sales_pivot
UNION ALL
SELECT 商品, '2月', 売上2月 FROM sales_pivot;

 


4. MySQL

MySQLには PIVOT 句はなく、CASE式 + GROUP BY を使う。

-- PIVOT
SELECT
  商品,
  SUM(CASE WHEN 月 = '1月' THEN 売上 END) AS 売上1月,
  SUM(CASE WHEN 月 = '2月' THEN 売上 END) AS 売上2月
FROM Sales
GROUP BY 商品;
UNPIVOTも標準構文がないので、PostgreSQL同様 UNION ALL を用いる。
-- UNPIVOT (UNION ALL)
SELECT 商品, '1月' AS 月, 売上1月 AS 売上 FROM sales_pivot
UNION ALL
SELECT 商品, '2月', 売上2月 FROM sales_pivot;

 


DBMS比較表

DBMSPIVOT対応UNPIVOT対応代替手段
SQL Serverネイティブネイティブそのまま使用可
Oracleネイティブネイティブそのまま使用可
PostgreSQLなしなしcrosstab関数 / UNION ALL
MySQLなしなしCASE式 + GROUP BY / UNION ALL

 

まとめ

  • SQL Server / Oracle → PIVOT/UNPIVOTがシンプルに使える。

  • PostgreSQL / MySQL → 標準ではなく、関数やCASE式で工夫が必要。

「集計を横に展開したい」あるいは「フラットに戻したい」とき、
DBMSに応じた方法を覚えておくと、データ整形がぐっと楽になります。

0 0
Article Rating
申し込む
注目する
guest
0 コメント一覧
最も古い
最新 高評価
インラインフィードバック
すべてのコメントを見る

Ads by Google

0 0
Article Rating
申し込む
注目する
guest
0 コメント一覧
最も古い
最新 高評価
インラインフィードバック
すべてのコメントを見る
0
あなたの考えが大好きです、コメントしてください。x