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

SQLServerの1つの列に基づいて複数の列をピボットする

    SQL Serverを使用しているため、行を列に変換する方法はいくつかあります。 CASE式で集計関数を使用できます:

    select empid,
      max(case when empindex = 1 then empstate end) empState1,
      max(case when empindex = 1 then empStDate end) empStDate1,
      max(case when empindex = 1 then empEndDate end) empEndDate1,
      max(case when empindex = 2 then empstate end) empState2,
      max(case when empindex = 2 then empStDate end) empStDate2,
      max(case when empindex = 2 then empEndDate end) empEndDate2
    from sourcetbl
    group by empid;
    

    SQL FiddlewithDemoを参照してください。

    PIVOT関数を使用して結果を取得する場合は、最初に列empStateのピボットを解除することをお勧めします。 、empStDate およびempEndDate したがって、最初に複数の行があります。 UNPIVOT関数またはCROSSAPPLYを使用して、コードが次のようになるデータを変換できます。

    select empid, col+cast(empindex as varchar(10)) col,  value
    from sourcetbl
    cross apply
    (
      select 'empstate', empstate union all
      select 'empstdate', convert(varchar(10), empstdate, 120) union all
      select 'empenddate', convert(varchar(10), empenddate, 120)
    ) c (col, value);
    

    デモを参照してください。データのピボットが解除されたら、PIVOT関数を適用して、最終的なコードを次のようにすることができます。

    select empid,
      empState1, empStDate1, empEndDate1,
      empState2, empStDate2, empEndDate2
    from 
    (
      select empid, col+cast(empindex as varchar(10)) col,  value
      from sourcetbl
      cross apply
      (
        select 'empstate', empstate union all
        select 'empstdate', convert(varchar(10), empstdate, 120) union all
        select 'empenddate', convert(varchar(10), empenddate, 120)
      ) c (col, value)
    ) d
    pivot
    (
      max(value)
      for col in (empState1, empStDate1, empEndDate1,
                  empState2, empStDate2, empEndDate2)
    ) piv;
    

    SQL FiddlewithDemoを参照してください。

    empindexの数が限られている場合は、上記のバージョンがうまく機能します 、ただしそうでない場合は、動的SQLを使用できます:

    DECLARE @cols AS NVARCHAR(MAX),
        @query  AS NVARCHAR(MAX)
    
    select @cols = STUFF((SELECT ',' + QUOTENAME(col+cast(empindex as varchar(10))) 
                        from SourceTbl
                        cross apply
                        (
                          select 'empstate', 1 union all
                          select 'empstdate', 2 union all
                          select 'empenddate', 3
                        ) c (col, so)
                        group by col, so, empindex
                        order by empindex, so
                FOR XML PATH(''), TYPE
                ).value('.', 'NVARCHAR(MAX)') 
            ,1,1,'')
    
    set @query = 'SELECT empid,' + @cols + ' 
                from 
                (
                    select empid, col+cast(empindex as varchar(10)) col,  value
                    from sourcetbl
                    cross apply
                    (
                      select ''empstate'', empstate union all
                      select ''empstdate'', convert(varchar(10), empstdate, 120) union all
                      select ''empenddate'', convert(varchar(10), empenddate, 120)
                    ) c (col, value)
                ) x
                pivot 
                (
                    max(value)
                    for col in (' + @cols + ')
                ) p '
    
    execute sp_executesql @query;
    

    SQL Fiddle with Demo

    を参照してください

    これらのクエリを使用して、DestTblに挿入できます。 、またはこの形式でデータを保存する代わりに、目的の結果を取得するためのクエリがあります。

    これらのクエリは、データを次の形式で配置します:

    | EMPID | EMPSTATE1 | EMPSTDATE1 | EMPENDDATE1 | EMPSTATE2 | EMPSTDATE2 | EMPENDDATE2 |
    ---------------------------------------------------------------------------------------
    |    10 |        AL | 2012-01-01 |  2012-12-01 |        FL | 2012-02-01 |  2013-02-01 |
    |    15 |        FL | 2012-03-20 |  2099-01-01 |    (null) |     (null) |      (null) |
    


    1. C#でのストアドプロシージャの出力パラメータの使用

    2. ClusterControlを使用したMySQL8.0の監視と運用管理

    3. ActiveRecordクエリの時間ベースの優先度

    4. 1つの列を複数の外部キーとして参照することは可能ですか?