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

SQL Serverで不明な数の列と集計なしをピボットする方法は?

    M.Aliの回答で結果が得られますが、SQL Server 2012を使用しているため、nameのピボットを解除します。 およびaddress 最終結果を得るには、列が少し異なります。

    SQL Server 2012を使用しているため、CROSS APPLYを使用できます。 VALUESを使用 これらの複数の列を複数の行にピボット解除します。ただし、その前に、row_number()を使用します 新しい列の総数を取得します。

    CROSSAPPLYを使用してデータを「UNPIVOT」するコードは次のようになります。

    select d.loanid, 
      col = c.col + cast(seq as varchar(10)),
      c.value
    from
    (
      select loanid, name, address,
        row_number() over(partition by loanid
                          order by loanid) seq
      from yourtable
    ) d
    cross apply
    (
      values
        ('name', name),
        ('address', address)
    ) c(col, value);
    

    SQL FiddlewithDemoを参照してください。これにより、データが次のような形式になります。

    | LOANID |      COL |    VALUE |
    |--------|----------|----------|
    |      1 |    name1 |     John |
    |      1 | address1 | New York |
    |      1 |    name2 |     Carl |
    |      1 | address2 | New York |
    |      1 |    name3 |    Henry |
    |      1 | address3 |   Boston |
    

    これで、単一の列COLが作成されました すべての新しい列名と関連付けられた値も1つの列にあります。新しい列名には、loanidごとのエントリの総数に基づいて、最後に番号(1、2、3など)が付けられます。 。これで、PIVOTを適用できます:

    select loanid,
      name1, address1, name2, address2,
      name3, address3
    from
    (
      select d.loanid, 
        col = c.col + cast(seq as varchar(10)),
        c.value
      from
      (
        select loanid, name, address,
          row_number() over(partition by loanid
                            order by loanid) seq
        from yourtable
      ) d
      cross apply
      (
        values
          ('name', name),
          ('address', address)
      ) c(col, value)
    ) src
    pivot
    (
      max(value)
      for col in (name1, address1, name2, address2,
                  name3, address3)
    ) piv;
    

    SQL FiddlewithDemoを参照してください。最後に、Nameのペアの数がわからない場合 およびAddress これで、動的SQLを使用できるようになります:

    DECLARE @cols AS NVARCHAR(MAX),
        @query  AS NVARCHAR(MAX)
    
    select @cols = STUFF((SELECT ',' + QUOTENAME(col+cast(seq as varchar(10))) 
                        from 
                        (
                          select row_number() over(partition by loanid
                                                    order by loanid) seq
                          from yourtable
                        ) d
                        cross apply
                        (
                          select 'Name', 1 union all
                          select 'Address', 2
                        ) c (col, so)
                        group by seq, col, so
                        order by seq, so
                FOR XML PATH(''), TYPE
                ).value('.', 'NVARCHAR(MAX)') 
            ,1,1,'')
    
    set @query = 'SELECT loanid,' + @cols + ' 
                from 
                (
                  select d.loanid, 
                    col = c.col + cast(seq as varchar(10)),
                    c.value
                  from
                  (
                    select loanid, name, address,
                      row_number() over(partition by loanid
                                        order by loanid) seq
                    from yourtable
                  ) d
                  cross apply
                  (
                    values
                      (''name'', name),
                      (''address'', address)
                  ) c(col, value)
                ) x
                pivot 
                (
                    max(value)
                    for col in (' + @cols + ')
                ) p '
    
    exec sp_executesql @query;
    

    SQL FiddlewithDemoを参照してください。どちらのバージョンでも結果が得られます:

    | LOANID |  NAME1 | ADDRESS1 |  NAME2 | ADDRESS2 |  NAME3 | ADDRESS3 |
    |--------|--------|----------|--------|----------|--------|----------|
    |      1 |   John | New York |   Carl | New York |  Henry |   Boston |
    |      2 | Robert |  Chicago | (null) |   (null) | (null) |   (null) |
    |      3 | Joanne |       LA |  Chris |       LA | (null) |   (null) |
    


    1. SQLServerで列名またはテーブル名の名前を変更する方法-SQLServer/T-SQLチュートリアルパート36

    2. PLSQLは、サブクエリと戻り句を使用して挿入します

    3. 重複するデータベースクエリを減らすためのデータベースキャッシングの形式はありません。

    4. プリペアドステートメントを使用したMySQLのLIMITキーワード