Oracle PIVOT/UNPIVOT 実践ガイド:エンジニア向けサンプル集

システム開発
スポンサーリンク
スポンサーリンク

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 は該当月のレコード数を数えます。SUMELSE 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_marNULL だった 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)

まとめ

PIVOTUNPIVOTは、データの見せ方や集計方法を柔軟に変更するための強力なツールです。

  • PIVOT: 縦持ちデータを分析しやすい横持ちデータへ変換。
  • UNPIVOT: 横持ちデータを集計しやすい縦持ちデータへ変換 (NULLの扱いに注意)。

これらの機能を活用し、データ操作の効率化を図ってください。

システム開発
スポンサーリンク
tobotoboをフォローする

コメント

タイトルとURLをコピーしました