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

行の値を動的な列数の列に変換するにはどうすればよいですか?

    PIVOTを使用しているときは常に、最初にハードコードされた値を使用してクエリを記述してから、クエリを動的ソリューションに簡単に変換することをお勧めします。

    columnCの値が複数あるため これは列に変換されるので、row_number()を使用して確認する必要があります columncごとに一意のシーケンスを生成するウィンドウ関数 columnAの値に基づく およびcolumnB

    クエリの開始点は次のとおりです。

    select [ColumnA],
      [ColumnB],
      [ColumnC],
      'SampleTitle'+
      cast(row_number() over(partition by columna, columnb
                              order by columnc) as varchar(10)) seq
    from DataSource;
    

    デモを参照してください。このクエリは、新しい列名のリストを生成しますSampleTitle1 、など:

    | COLUMNA | COLUMNB | COLUMNC |          SEQ |
    |---------|---------|---------|--------------|
    |    5060 |    1006 |  100118 | SampleTitle1 |
    |    5060 |    1006 |  100119 | SampleTitle2 |
    |    5060 |    1006 |  100120 | SampleTitle3 |
    

    次に、columnCにピボットを適用できます seqにリストされている新しい列名 :

    select columnA, columnB, 
      SampleTitle1, SampleTitle2, SampleTitle3
    from
    (
       select [ColumnA],
        [ColumnB],
        [ColumnC],
        'SampleTitle'+
          cast(row_number() over(partition by columna, columnb
                                  order by columnc) as varchar(10)) seq
       from DataSource
    ) d
    pivot
    (
      max(columnc)
      for seq in (SampleTitle1, SampleTitle2, SampleTitle3)
    ) piv;
    

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

    正しいロジックができたら、データを動的SQLに変換できます。ここで重要なのは、新しい列名のリストを生成することです。私は通常、FOR XML PATHを使用します これは次のようになります:

    select STUFF((SELECT distinct ',' + QUOTENAME(seq) 
                    from
                    (
                      select 'SampleTitle'+
                        cast(row_number() over(partition by columna, columnb
                                                order by columnc) as varchar(10)) seq
                      from DataSource
                    ) d
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')
    

    デモを参照してください。列名のリストを取得したら、実行するSQL文字列を生成します。完全なコードは次のようになります。

    DECLARE @cols AS NVARCHAR(MAX),
        @query  AS NVARCHAR(MAX)
    
    select @cols = STUFF((SELECT distinct ',' + QUOTENAME(seq) 
                        from
                        (
                          select 'SampleTitle'+
                            cast(row_number() over(partition by columna, columnb
                                                    order by columnc) as varchar(10)) seq
                          from DataSource
                        ) d
                FOR XML PATH(''), TYPE
                ).value('.', 'NVARCHAR(MAX)') 
            ,1,1,'')
    
    set @query = 'SELECT columnA, ColumnB,' + @cols + ' 
                 from 
                 (
                   select [ColumnA],
                    [ColumnB],
                    [ColumnC],
                    ''SampleTitle''+
                      cast(row_number() over(partition by columna, columnb
                                              order by columnc) as varchar(10)) seq
                   from DataSource
                ) x
                pivot 
                (
                    max(columnc)
                    for seq in (' + @cols + ')
                ) p '
    
    execute sp_executesql @query;
    

    SQL FiddlewithDemoを参照してください。これらは結果をもたらします:

    | COLUMNA | COLUMNB | SAMPLETITLE1 | SAMPLETITLE2 | SAMPLETITLE3 |
    |---------|---------|--------------|--------------|--------------|
    |    5060 |    1006 |       100118 |       100119 |       100120 |
    |    5060 |    1007 |       100121 |       100122 |       (null) |
    |    5060 |    1012 |       100123 |       (null) |       (null) |
    



    1. LAST_DAY()がMariaDBでどのように機能するか

    2. PreparedStatementでのsetDateの使用

    3. SELECT *ステートメントの列の順序-保証されていますか?

    4. 並行プログラムの優先順位を変更する方法