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

個別のレコードに対するPIVOTクエリ

    ROW_NUMBER()をミックスに追加すると、ピボットはアクティビティとパーセンテージの間の関連付けを保持できるようになります。

    ;with cte as 
    (
        select *, ROW_NUMBER() over (partition by name order by percentage desc) ROWNUM
        from A
    ),
    cte2 as
    (
        SELECT Id,Code,ROWNUM,James,James_,Sam,Sam_,Lisa,Lisa_
        FROM cte
        PIVOT(MAX(activity)
              FOR name IN (James,Sam,Lisa)) AS PVTTable PIVOT
              (
              MAX(percentage)
              FOR name1 IN (James_,Sam_,Lisa_)) AS PVTTable1
    )
    select Id, Code, MAX(James) James, MAX(James_) James_, MAX(Sam) Sam, MAX(Sam_) Sam_, MAX(Lisa) Lisa, MAX(Lisa_) Lisa_
    from cte2
    group by Id, Code, ROWNUM
    

    返品:

    Id  Code        James       James_  Sam         Sam_    Lisa    Lisa_
    1   Prashant    Running     43.43   Cooking 1   73      Walking 90.34
    1   Prashant    Stealing    0.00    Cooking     3.43    NULL    NULL
    1   Prashant    Lacking     0.00    NULL        NULL    NULL    NULL
    

    アイデアは、最初の一般的なテーブル式で、Aテーブルを次のように変換することです。

    Id  Code        percentage  name    name1   activity    ROWNUM
    1   Prashant    43.43       James   James_  Running     1
    1   Prashant    0.00        James   James_  Stealing    2
    1   Prashant    0.00        James   James_  Lacking     3
    1   Prashant    90.34       Lisa    Lisa_   Walking     1
    1   Prashant    73          Sam     Sam_    Cooking 1   1
    1   Prashant    3.43        Sam     Sam_    Cooking     2
    

    そして、残りのクエリ全体で、ROWNUM列はパーセンテージ値をアクティビティにバインドするように機能します。

    クエリが機能するようになったら、動的にするのは簡単です。すべての動的部分(この場合、名前のコンマ区切りのリストですよね?)を変数に置き換えるだけです。このようなもの:

    declare @sql nvarchar(max)
    declare @name_concat nvarchar(max)
    declare @name1_concat nvarchar(max)
    declare @select_aggs nvarchar(max)
    select @name_concat = STUFF((select distinct ',' + quotename(name) from A order by 1 for xml path('')), 1, 1, '')
    select @name1_concat = STUFF((select distinct ',' + quotename(name1) from A order by 1 for xml path('')), 1, 1, '')
    
    ;with cte_all_names as (
        select name from A
        union all 
        select name1 from A
    )
    select @select_aggs = STUFF((select distinct ',MAX(' + quotename(name) + ') ' + quotename(name) from cte_all_names order by 1 for xml path('')), 1, 1, '')
    
    select @sql = '
    ;with cte as 
    (
        select *, ROW_NUMBER() over (partition by name order by percentage desc) ROWNUM
        from A
    ),
    cte2 as
    (
        SELECT Id,Code,ROWNUM,' + @name_concat + ',' + @name1_concat + '
        FROM cte
        PIVOT(MAX(activity)
              FOR name IN (' + @name_concat + ')) AS PVTTable PIVOT
              (
              MAX(percentage)
              FOR name1 IN (' + @name1_concat + ')) AS PVTTable1
    )
    select Id, Code, ' + @select_aggs + '
    from cte2
    group by Id, Code, ROWNUM
    '
    
    exec sp_executesql @sql
    



    1. SQLエラーの読み取りと解釈の方法

    2. 最適化フェーズと逃した機会

    3. SQL左結合

    4. MySQL-既存のフィールドを一意にする