PIVOT on Multiple Columns

前端 未结 3 592
南旧
南旧 2021-01-26 20:41

I have data like this:

Product Group     Product Level    Quatity Sold     Trend
==============================================================
Group 1                   


        
相关标签:
3条回答
  • 2021-01-26 20:49

    You could get the desired result by implementing the PIVOT function, but I would first UNPIVOT your multiple columns of Quantity Sold and Trend. The unpivot process will convert them from multiple columns into multiple rows of data.

    Since you are using SQL Server 2008+, you can use CROSS APPLY with VALUES to unpivot the data:

    select [Product Group], 
      col, value
    from yourtable
    cross apply
    (
      values
        ([Product Level], cast([Quatity Sold] as varchar(10))),
        ([Product Level]+'trend', [trend])
    ) c (col, value);
    

    See SQL Fiddle with Demo This converts your table data into the format:

    | PRODUCT GROUP |     COL | VALUE |
    |---------------|---------|-------|
    |       Group 1 |      L1 |    10 |
    |       Group 1 | L1trend |    up |
    |       Group 1 |      L2 |    20 |
    |       Group 1 | L2trend |    up |
    |       Group 1 |      L3 |    30 |
    |       Group 1 | L3trend |  down |
    

    Now you can easily apply the PIVOT function:

    select [Product Group],
      L1, L1trend, 
      L2, L2trend,
      L3, L3trend, 
      L4, L4trend
    from
    (
      select [Product Group], 
        col, value
      from yourtable
      cross apply
      (
        values
          ([Product Level], cast([Quatity Sold] as varchar(10))),
          ([Product Level]+'trend', [trend])
      ) c (col, value)
    ) d
    pivot
    (
      max(value)
      for col in (L1, L1trend, L2, L2trend,
                  L3, L3trend, L4, L4trend)
    ) piv;
    

    See SQL Fiddle with Demo. This gives you a final result of:

    | PRODUCT GROUP | L1 | L1TREND | L2 | L2TREND | L3 | L3TREND |     L4 | L4TREND |
    |---------------|----|---------|----|---------|----|---------|--------|---------|
    |       Group 1 | 10 |      up | 20 |      up | 30 |    down | (null) |  (null) |
    |       Group 2 | 20 |      up | 40 |      up | 60 |    down |     80 |    down |
    
    0 讨论(0)
  • 2021-01-26 20:58

    You can potentially do this using correlated subqueries:

    select productGroup as [Product Group]
        , (select sum(quantitySold) from myTable where productGroup = a.productGroup and productLevel = 'L1') as L1
        , (select max(trend) from myTable where productGroup = a.productGroup and productLevel = 'L1') as L1Trend
        , (select sum(quantitySold) from myTable where productGroup = a.productGroup and productLevel = 'L2') as L2
        , (select max(trend) from myTable where productGroup = a.productGroup and productLevel = 'L2') as L2Trend
        -- etc.
    from myTable a
    group by productGroup 
    order by productGroup
    

    Here's an example SqlFiddle.

    It may help you to see it this way before you use the PIVOT keyword.

    If you don't know how many productLevel values you have, you'd need a dynamic solution, however.

    0 讨论(0)
  • 2021-01-26 21:11

    if you prefer to use pivot you can try this one:

    select productgroup, 
    coalesce(L1up,L1down,'') L1, case when L1up is not null then 'up' when L1down is not null then 'down' else '' end L1trend,
    coalesce(L2up,L2down,'') L2, case when L2up is not null then 'up' when L2down is not null then 'down' else '' end L2trend,
    coalesce(L3up,L3down,'') L3, case when L3up is not null then 'up' when L3down is not null then 'down' else '' end L3trend,
    coalesce(L4up,L4down,'') L4, case when L4up is not null then 'up' when L4down is not null then 'down' else '' end L4trend
    from
    (
    select productgroup, [L1up],[L2up],[L3up],[L4up],[L1down],[L2down],[L3down],[L4down] 
    from (select productgroup, productlevel+trend pt, quantity from mytable) t
    PIVOT (MAX(quantity)
    FOR pt IN([L1up],[L2up],[L3up],[L4up],[L1down],[L2down],[L3down],[L4down] )) as p
    ) t
    
    0 讨论(0)
提交回复
热议问题