在SQL中多次旋转同一列

时间:2019-07-22 22:43:57

标签: sql sql-server pivot-table

我已经搜索了整个站点,尽管对此问题有多个疑问,但由于我是SQL的新手,所以我不能完全理解它们,或者它们不完全适合我的问题。

所以我有一个这样的表:

ID  Label   AmountA AmountB CurrA   CurrB
1   7         400   4        usd    usd
2   7         500   10       eur    eur
3   7         1000  500      usd    usd
1   8         800   1        usd    usd
2   8         9000  0        eur    eur
3   9         100   0        usd    usd

但是我需要这样:

ID  AmountA1    CurrAmountA1    AmountA2    CurrAmountA2    AmountA3    CurrAmountA3    AmountB1    CurrAmountB1    AmountB2    CurrAmountB2    AmountB3    CurrAmountB3
 1  400         USD             800         USD             NULL        NULL            4            USD            1            USD            NULL        NULL
 2  500         EUR             9000        EUR             NULL        NULL            10           EUR            0            EUR            NULL        NULL
 3  1000        USD             NULL        NULL            100         USD             500          USD            NULL         NULL           0           USD

我设法执行了以下代码:

SELECT ID,
isnull([7],0) as AmountA1, 
isnull([8],0) as AmountA2, 
isnull([9],0) as AmountA3, 
FROM 
(SELECT ID, Label, AmountA, AmountB,CurrA, CurrB FROM mytable ) ps
PIVOT
( sum([AmountA]) FOR Label IN
( [7], 
[8], 
[9])) as pvt

我只希望调整AmountA的位置,但是我不知道如何包含其他AmountA的方法。

我不知道是否值得一提,我需要对数百万行执行此操作,并且Label可以具有10个不同的值,并且我希望它要尽可能快。

谢谢

2 个答案:

答案 0 :(得分:1)

我只会使用条件聚合:

select id,
       max(case when seqnum = 1 then amountA end) as amountA_1,
       max(case when seqnum = 1 then currA end) as currA_1,
       max(case when seqnum = 2 then amountA end) as amountA_2,
       max(case when seqnum = 2 then currA end) as currA_2,
       max(case when seqnum = 3 then amountA end) as amountA_3,
       max(case when seqnum = 3 then currA end) as currA_3,
       max(case when seqnum = 1 then amountB end) as amountB_1,
       max(case when seqnum = 1 then currB end) as currB_1,
       max(case when seqnum = 2 then amountB end) as amountB_2,
       max(case when seqnum = 2 then currB end) as currB_2,
       max(case when seqnum = 3 then amountB end) as amountB_3,
       max(case when seqnum = 3 then currB end) as currB_3
from (select t.*,
             row_number() over (partition by id order by label) as seqnum
      from t
     ) t
group by id;

答案 1 :(得分:0)

您可以尝试此查询。 SQLServer不允许我们给子句Pivot中的枢轴列提供别名。因此,为了避免数据透视冲突列错误,我们可以做一个“变通”来声明许多Label列,并连接一个值以创建另一种Label。最后,由于表中有许多相等的ID,因此我们按ID collumn进行分组。

这里是我对此进行测试的链接:http://sqlfiddle.com/#!18/26a01/6

Select ID, Max(isnull([7],0)) as AmountA7, 
           max(isnull([7-3],0)) as CurrA7, 
           max(isnull([8],0)) as AmountA8, 
           max(isnull([8-3],0)) as CurrA8, 
           max(isnull([9],0)) as AmountA9, 
           max(isnull([9-3],0)) as CurrA9, 
           max(isnull([7-2],0)) as AmountB7, 
           max(isnull([7-4],0)) as CurrB7, 
           max(isnull([8-2],0)) as AmountB8, 
           max(isnull([8-4],0)) as CurrB8, 
           max(isnull([9-2],0)) as AmountB9, 
           max(isnull([9-4],0)) as CurrB9
  from
( 
 select Label LabelAAmount, CONCAT(Label, '-2') LabelBAmount, CONCAT(Label,'-3') LabelACurr, CONCAT(Label, '-4') LabelBCurr, ID, AmountA, AmountB, CurrA, CurrB
  from myTable
) ps
PIVOT
(Sum(AmountA) for LabelAAmount IN ([7],
                                     [8],
                                     [9])
) as pvtAmountA
pivot
(Sum(AmountB) for LabelBAmount in ([7-2],
                                   [8-2],
                                   [9-2])
) as pvtAmountB                      
pivot
(Max(CurrA) for LabelACurr in ([7-3],
                               [8-3],
                               [9-3])
) as pvtCurrA
pivot
(Max(CurrB) for LabelBCurr in ([7-4],
                               [8-4],
                               [9-4])
) as pvtCurrB
group by id