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

SQL Server:5列にわたる動的ピボット

    結果を取得するには、Totalのデータのピボット解除を確認する必要があります およびVolume 最終結果を取得するためにPIVOT関数を適用する前に、最初に列を作成します。私の提案は、最初にハードコードされたバージョンのクエリを記述してから、それを動的SQLに変換することです。

    UNPIVOTプロセスは、これらの複数の列を行に変換します。 UNPIVOTにはいくつかの方法があります。UNPIVOT機能を使用するか、CROSSAPPLYを使用できます。データのピボットを解除するコードは次のようになります:

    select id, 
        col = cast(t_year as varchar(4))+'_'+t_type+'_'+col, 
        value
    from ATM_TRANSACTIONS t
    cross apply
    (
        select 'total', total union all
        select 'volume', volume
    ) c (col, value);
    

    これにより、次の形式のデータが得られます:

    +-----+---------------+-------+
    | id  |      col      | value |
    +-----+---------------+-------+
    | DD1 | 2008_A_total  |  1000 |
    | DD1 | 2008_A_volume |    10 |
    | DD1 | 2008_B_total  |  2000 |
    | DD1 | 2008_B_volume |    20 |
    | DD1 | 2008_C_total  |  3000 |
    | DD1 | 2008_C_volume |    30 |
    +-----+---------------+-------+
    

    次に、PIVOT関数を適用できます:

    select ID, 
        [2008_A_total], [2008_A_volume], [2008_B_total], [2008_B_volume],
        [2008_C_total], [2008_C_volume], [2009_A_total], [2009_A_volume]
    from
    (
        select id, 
            col = cast(t_year as varchar(4))+'_'+t_type+'_'+col, 
            value
        from ATM_TRANSACTIONS t
        cross apply
        (
            select 'total', total union all
            select 'volume', volume
        ) c (col, value)
    ) d
    pivot
    (
        max(value)
        for col in ([2008_A_total], [2008_A_volume], [2008_B_total], [2008_B_volume],
                    [2008_C_total], [2008_C_volume], [2009_A_total], [2009_A_volume])
    ) piv;
    

    正しいロジックができたので、これを動的SQLに変換できます。

    DECLARE @cols AS NVARCHAR(MAX),
        @query  AS NVARCHAR(MAX)
    
    select @cols = STUFF((SELECT ',' + QUOTENAME(cast(t_year as varchar(4))+'_'+t_type+'_'+col) 
                        from ATM_TRANSACTIONS t
                        cross apply
                        (
                            select 'total', 1 union all
                            select 'volume', 2
                        ) c (col, so)
                        group by col, so, T_TYPE, T_YEAR
                        order by T_YEAR, T_TYPE, so
                FOR XML PATH(''), TYPE
                ).value('.', 'NVARCHAR(MAX)') 
            ,1,1,'')
    
    set @query = 'SELECT id,' + @cols + ' 
                from 
                (
                    select id, 
                        col = cast(t_year as varchar(4))+''_''+t_type+''_''+col, 
                        value
                    from ATM_TRANSACTIONS t
                    cross apply
                    (
                        select ''total'', total union all
                        select ''volume'', volume
                    ) c (col, value)
                ) x
                pivot 
                (
                    max(value)
                    for col in (' + @cols + ')
                ) p '
    
    execute sp_executesql @query;
    

    これにより、結果が得られます:

    +-----+--------------+---------------+--------------+---------------+--------------+---------------+--------------+---------------+--------------+---------------+--------------+---------------+
    | id  | 2008_A_total | 2008_A_volume | 2008_B_total | 2008_B_volume | 2008_C_total | 2008_C_volume | 2009_A_total | 2009_A_volume | 2009_B_total | 2009_B_volume | 2009_C_total | 2009_C_volume |
    +-----+--------------+---------------+--------------+---------------+--------------+---------------+--------------+---------------+--------------+---------------+--------------+---------------+
    | DD1 |         1000 |            10 |         2000 |            20 |         3000 |            30 |         4000 |            40 |         5000 |            50 |         6000 |            60 |
    | DD2 |         7000 |            70 |         8000 |            80 |         9000 |            90 |        10000 |           100 |        11000 |           110 |         1200 |           120 |
    +-----+--------------+---------------+--------------+---------------+--------------+---------------+--------------+---------------+--------------+---------------+--------------+---------------+
    


    1. SQLServerで同じクエリを複数回実行する最も簡単な方法

    2. OracleインデックスとOracleのインデックスの種類と例

    3. SQL:ビットまたはchar(1)のどちらが優れているか

    4. EBSR12コンポーネントのバージョンを見つける方法