多列上的PIVOT

时间:2014-01-20 22:59:34

标签: sql sql-server tsql sql-server-2008-r2 pivot

我有这样的数据:

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

我需要以这种格式获取数据:

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

我可以通过使用类似的东西来转向“产品级别”

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

但在处理趋势时迷失了方法。

感谢。

3 个答案:

答案 0 :(得分:3)

您可以通过实施PIVOT功能获得所需的结果,但我会首先将您的多列Quantity SoldTrend取消。 unpivot进程将它们从多列转换为多行数据。

由于您使用的是SQL Server 2008+,因此可以CROSS APPLY使用VALUES来取消数据的转出:

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);

请参阅SQL Fiddle with Demo这会将您的表数据转换为以下格式:

| 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 |

现在您可以轻松应用PIVOT功能:

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;

SQL Fiddle with Demo。这样可以得到最终结果:

| 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 |

答案 1 :(得分:0)

您可以使用相关子查询来执行此操作:

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

这是一个example SqlFiddle

在您使用PIVOT关键字之前,可以帮助您以这种方式查看。

如果你不知道你有多少个productLevel值,你需要一个动态的解决方案。

答案 2 :(得分:0)

如果你更喜欢使用数据透视,你可以试试这个:

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