sql >> データベース >  >> RDS >> Sqlserver

SQL 2012 - ピボットとアンピボット

    動的 SQL を使用してテーブルを転置できます:

    DECLARE @cols NVARCHAR(MAX) = 
                    STUFF((SELECT DISTINCT ',' + QUOTENAME(CONCAT([Year], '_', [Month]))
                          FROM #tab
                          FOR XML PATH(''), TYPE
                         ).value('.', 'NVARCHAR(MAX)') 
                         , 1, 1, '');
    
    DECLARE @query NVARCHAR(MAX) = 
    FORMATMESSAGE(
    N'SELECT col_name, customer, %s
    FROM (SELECT [year_month] = CONCAT([Year], ''_'', [Month]),
                 Customer, No_Trans, spend, points
          FROM #tab) AS sub
    UNPIVOT
    (
        val FOR col_name  IN (No_trans, spend, points)
    ) AS unpvt
    PIVOT
    (
        MAX(val) FOR [year_month] IN (%s)
    ) AS pvt
    ORDER BY customer, col_name;', @cols, @cols); 
    
    EXEC [dbo].[sp_executesql] @query;
    

    LiveDemo

    出力:

    ╔══════════╦══════════╦════════╦════════╦════════╗
    ║   col    ║ customer ║ 2015_1 ║ 2015_2 ║ 2015_3 ║
    ╠══════════╬══════════╬════════╬════════╬════════╣
    ║ No_Trans ║        1 ║     30 ║     20 ║     10 ║
    ║ points   ║        1 ║     10 ║      5 ║     15 ║
    ║ spend    ║        1 ║    400 ║    150 ║    500 ║
    ║ No_Trans ║        2 ║      5 ║        ║        ║
    ║ points   ║        2 ║      7 ║        ║        ║
    ║ spend    ║        2 ║    100 ║        ║        ║
    ╚══════════╩══════════╩════════╩════════╩════════╝
    

    zerosが必要な場合 不足している位置で ISNULL/COALESCE を使用できます .すべてのデータ型が 0 (int) に置き換えられるわけではないことに注意してください

    LiveDemo2

    編集:

    FORMATMESSAGE %s を置き換える素晴らしい方法です ひも付き。シンプルな REPLACE で簡単に変更できます :

     DECLARE @query NVARCHAR(MAX) = 
     N'SELECT col1, col2, <placeholder>
       FROM ...
       ...
       PIVOT( MAX(col) IN col2 IN (<placeholder>)
       ...';
    
     SET @query = REPLACE(@query, '<placeholder', @cols);
    
     -- for debug
     PRINT @query;
    

    仕組み:

    <オール>
  1. 生成 [year_month] サブクエリの列
  2. UNPIVOT データ (列から行へ)
  3. PIVOT 結果 (行から列へ)
  4. 動的 SQL でラップして、[year_month] を知らなくても列を生成できるようにします



    1. mysqlutf8mb4_unicode_ciは一意のキーの衝突を引き起こします

    2. varchar 値 'none' をデータ型 int に変換するときに変換に失敗しました

    3. テーブル全体のハッシュを計算する最速の方法

    4. 削除されたデータ (複数のレコード) を Production テーブルに保存するトリガーを作成する方法