Oracle Database 11g以降で導入されたPIVOT
およびUNPIVOT
句は、データ集計や分析において、行と列の形式を効率的に変換するための強力な機能です。ここでは、エンジニアが実務で活用できるよう、具体的なサンプルコードとその入出力を中心に解説します。
PIVOT:行データを列データに変換する
PIVOT
句は、特定の列の値を新しい列名とし、集計関数を用いてデータを横持ち(列形式)に変換します。
✅ 基本構文:
SELECT *
FROM ( <元のSELECT文> )
PIVOT (
<集計関数>(<集計対象列>)
FOR <ピボット対象列> IN ( <値1> AS <別名1>, <値2> AS <別名2>, ... )
);
サンプル1: 基本的なPIVOT (月ごとの売上合計)
製品ごとの月別売上合計を列として表示します。
🔹元のデータ (sales_data
):
product_name | sale_month | amount |
---|---|---|
Product A | 2025-01 | 1000 |
Product B | 2025-01 | 1500 |
Product A | 2025-02 | 1200 |
… | … | … |
🔹実行するSQL:
SELECT *
FROM (
SELECT product_name, sale_month, amount
FROM sales_data
)
PIVOT (
SUM(amount) -- 売上合計を集計
FOR sale_month IN (
'2025-01' AS sales_jan
,'2025-02' AS sales_feb
,'2025-03' AS sales_mar) -- 月を列に変換
);
🔹出力結果:
product_name | sales_jan | sales_feb | sales_mar |
---|---|---|---|
Product A | 1000 | 1200 | 1100 |
Product B | 1500 | 1600 | (null) |
Product C | 800 | 900 | (null) |
サンプル2: 複数指標のPIVOT (CASE
文を使用)
月ごとの「売上合計」と「販売件数」の両方を列として表示します。標準のPIVOT
句では直接的な複数集計が扱いにくいため、CASE
文を使うのが一般的です。
🔹元のデータ (sales_data
):
product_name | sale_month | amount |
---|---|---|
Product A | 2025-01 | 1000 |
Product B | 2025-01 | 1500 |
Product A | 2025-02 | 1200 |
… | … | … |
🔹実行するSQL:
SELECT
product_name,
SUM(CASE WHEN sale_month = '2025-01' THEN amount ELSE 0 END) AS amount_jan,
COUNT(CASE WHEN sale_month = '2025-01' THEN 1 END) AS count_jan,
SUM(CASE WHEN sale_month = '2025-02' THEN amount ELSE 0 END) AS amount_feb,
COUNT(CASE WHEN sale_month = '2025-02' THEN 1 END) AS count_feb,
SUM(CASE WHEN sale_month = '2025-03' THEN amount ELSE 0 END) AS amount_mar,
COUNT(CASE WHEN sale_month = '2025-03' THEN 1 END) AS count_mar
FROM sales_data
GROUP BY product_name;`
🔹出力結果:
product_name | amount_jan | count_jan | amount_feb | count_feb | amount_mar | count_mar |
---|---|---|---|---|---|---|
Product A | 1000 | 1 | 1200 | 1 | 1100 | 1 |
Product B | 1500 | 1 | 1600 | 1 | 0 | 0 |
Product C | 800 | 1 | 900 | 1 | 0 | 0 |
💬 COUNT
は該当月のレコード数を数えます。SUM
の ELSE 0
は合計値に影響しないようにしています
UNPIVOT:列データを行データに変換する
UNPIVOT
句は、複数の列データを縦持ち(行形式)に変換します。
✅ 基本構文:
SELECT <保持する列>, <新しい名称列>, <新しい値列>
FROM <元のテーブル もしくは SELECT文>
UNPIVOT [INCLUDE NULLS | EXCLUDE NULLS] ( -- デフォルトは EXCLUDE NULLS
<新しい値列>
FOR <新しい名称列> IN ( <元の列1> AS <名称1>, <元の列2> AS <名称2>, ... )
);
サンプル3: 基本的なUNPIVOT (デフォルト – NULL除外)
月別売上列を行データ(月と売上)に変換します。デフォルト (EXCLUDE NULLS
) では、元の値がNULLの行は生成されません。
🔹元のデータ (monthly_sales_pivot
):
product_name | sales_jan | sales_feb | sales_mar |
---|---|---|---|
Product A | 1000 | 1200 | 1100 |
Product B | 1500 | 1600 | (null) |
Product C | 800 | 900 | (null) |
🔹実行するSQL:
SELECT product_name, sale_month, amount
FROM monthly_sales_pivot
UNPIVOT ( -- EXCLUDE NULLS がデフォルト
amount -- 値を格納する新しい列名
FOR sale_month -- 列名を格納する新しい列名
IN (
sales_jan AS '2025-01'
, sales_feb AS '2025-02'
, sales_mar AS '2025-03') -- 対象列と変換後の名称
);
🔹出力結果:
product_name | sale_month | amount |
---|---|---|
Product A | 2025-01 | 1000 |
Product A | 2025-02 | 1200 |
Product A | 2025-03 | 1100 |
Product B | 2025-01 | 1500 |
Product B | 2025-02 | 1600 |
Product C | 2025-01 | 800 |
Product C | 2025-02 | 900 |
💬 sales_mar
が NULL
だった Product B, C の行は出力されません
サンプル4: NULL値を含むUNPIVOT (INCLUDE NULLS
)
INCLUDE NULLS
を指定して、元の値がNULLの場合も行として出力します。
🔹元のデータ (monthly_sales_pivot
):
product_name | sales_jan | sales_feb | sales_mar |
---|---|---|---|
Product A | 1000 | 1200 | 1100 |
Product B | 1500 | 1600 | (null) |
Product C | 800 | 900 | (null) |
🔹実行するSQL:
SELECT product_name, sale_month, amount
FROM monthly_sales_pivot
UNPIVOT INCLUDE NULLS ( -- NULL値も行として含める
amount
FOR sale_month
IN (
sales_jan AS '2025-01'
, sales_feb AS '2025-02'
, sales_mar AS '2025-03')
);
🔹出力結果:
product_name | sale_month | amount |
---|---|---|
Product A | 2025-01 | 1000 |
Product A | 2025-02 | 1200 |
Product A | 2025-03 | 1100 |
Product B | 2025-01 | 1500 |
Product B | 2025-02 | 1600 |
Product B | 2025-03 | (null) |
Product C | 2025-01 | 800 |
Product C | 2025-02 | 900 |
Product C | 2025-03 | (null) |
まとめ
PIVOT
とUNPIVOT
は、データの見せ方や集計方法を柔軟に変更するための強力なツールです。
- PIVOT: 縦持ちデータを分析しやすい横持ちデータへ変換。
- UNPIVOT: 横持ちデータを集計しやすい縦持ちデータへ変換 (
NULL
の扱いに注意)。
これらの機能を活用し、データ操作の効率化を図ってください。
コメント