PIVOT on Multiple Columns

╄→гoц情女王★ 提交于 2019-12-02 12:40:15

问题


I have data like this:

Product Group     Product Level    Quatity Sold     Trend
==============================================================
Group 1           L1                10               up
Group 1           L2                20               up
Group 1           L3                30               down
Group 2           L1                20               up
Group 2           L2                40               up
Group 2           L3                60               down
Group 2           L4                80               down

I need to get the data in this format:

Product Group     L1      L1Trend    L2    L2Trend    L3    L3Trend    L4     L4Trend
======================================================================================
Group 1           10      up         20    up         30    down
Group 2           20      up         40    up         60    down       80     down

I was able to pivot on "Product Level" by using something like:

PIVOT (MAX(quatity)     FOR productlevel IN([L1],[L2],[L3],[L4]) AS p

but got lost when dealing with the trend.

Thanks.


回答1:


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 |



回答2:


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.




回答3:


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


来源:https://stackoverflow.com/questions/21245893/pivot-on-multiple-columns

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!