T-Sql Pivot 使用不同的聚合 FOR 值列

问题描述 投票:0回答:1

您好,我需要在列中添加“R”类型的前 6 件商品和任何其他类型的前 3 件商品的日期和金额。以字母“a”开头的列来自不同的聚合列。 我设法按照下面的代码做到这一点,但是有没有更简单和最佳的方法?我的代码查询源表中需要旋转的每一列,这是两次。

Create Table #TmpChgs (dPer VarChar(25)
                      ,dAmnt Money
                      ,sFlag VarChar(20)    
                      )
Insert Into #TmpChgs
        Select '2408.Aug-24',0, 'R'
        Union all
        Select '2407.Jul-24',188, 'R'
        Union all
        Select '2401.Jan-24',250, 'R'
        Union all
        Select '2406.Jun-24',325, 'R'
        Union all
        Select '2405.May-24',118, 'R'
        Union all
        Select '2404.Apr-24',0, 'R'
        Union all
        Select '2403.Mar-24',0, 'R'
        Union all
        Select '2402.Feb-24',175, 'R'
        Union all
        Select '2312.Dec-23',0, 'R'
        Union all
        Select '2311.Nov-22',480, 'R'
        Union all
        Select '2310.Oct-23',114, 'R'
        Union all
        Select '2408.Aug-24',0, 'M'
        Union all
        Select '2407.Jul-24',188, 'M'
        Union all
        Select '2401.Jan-24',250, 'M'
        Union all
        Select '2406.Jun-24',325, 'C'
        Union all
        Select '2405.May-24',118, 'C'
        Union all
        Select '2404.Apr-24',0, 'M'
        Union all
        Select '2403.Mar-24',0, 'C'
        Union all
        Select '2402.Feb-24',175, 'M'
        Union all
        Select '2312.Dec-23',0, 'C'
        Union all
        Select '2311.Nov-22',480, 'C'
        Union all
        Select '2310.Oct-23',114, 'C'
/* Select top 6 R items non 0 order by period and top 3 M or C items non 0 of second type*/
Select Isnull(dt.sType,a.sType) rtype, R1,R2,R3,R4,R5,R6,aR1,aR2,aR3,aR4,aR5,aR6,O1,O2,O3,aO1,aO2,aO3
From
(
Select sFlag As sType
       ,[R1],[R2],[R3],[R4],[R5],[R6],[O1],[O2],[O3]
FROM (
       Select Case When sFlag='R' Then 'R' Else 'O' End + Cast(ROW_NUMBER() OVER(Partition By sFlag Order By dPer desc) as VarChar(10))  As sPer
              ,dPer 
              ,sFlag
       From  #TmpChgs
       Where dAmnt>0
      ) As pdt
PIVOT
( Max(dPer) FOR sPer IN ([R1],[R2],[R3],[R4],[R5],[R6],[O1],[O2],[O3])
) as dtPvt
) as dt
Full Outer Join
(Select sFlag As sType
       ,[aR1],[aR2],[aR3],[aR4],[aR5],[aR6],[aO1],[aO2],[aO3]
FROM (
       Select Case When sFlag='R' Then 'aR' Else 'aO' End + Cast(ROW_NUMBER() OVER(Partition By sFlag Order By dPer desc) as VarChar(10))  As sPer
              ,dAmnt 
              ,sFlag
       From  #TmpChgs
       Where dAmnt>0
      ) As pdt
PIVOT
( Sum(dAmnt) FOR sPer IN ([aR1],[aR2],[aR3],[aR4],[aR5],[aR6],[aO1],[aO2],[aO3])
) as aPvt
) as A On dt.sType=A.sType

结果看起来不错,但我担心此查询针对日期量较大的表运行时的性能。

r类型 R1 R2 R3 R4 R5 R6 aR1 aR2 aR3 aR4 aR5 aR6 O1 氧气 O3 aO1 aO2 aO3
C 2406.6月24日 2405.5月24日 2311.11 月 22 日 325.00 118.00 480.00
M 2407.7 月 24 日 2402.2 月 24 日 2401.1月24日 188.00 175.00 250.00
R 2407.7 月 24 日 2406.6月24日 2405.5月24日 2402.2 月 24 日 2401.1月24日 2311.11 月 22 日 188.00 325.00 118.00 175.00 250.00 480.00

Query Execution plan

sql-server t-sql pivot query-optimization
1个回答
0
投票

您可以使用条件 case 表达式来执行所需的旋转。

with cte as
(
  Select sFlag,
         rn = ROW_NUMBER() OVER(Partition By sFlag Order By dPer desc),
         dPer,
         dAmnt
  From  #TmpChgs
  Where dAmnt > 0
)
select rtype = sFlag,
       R1    = max(case when sFlag =  'R' and rn = 1 then dPer end),
       R2    = max(case when sFlag =  'R' and rn = 2 then dPer end),
       R3    = max(case when sFlag =  'R' and rn = 3 then dPer end),
       R4    = max(case when sFlag =  'R' and rn = 4 then dPer end),
       R5    = max(case when sFlag =  'R' and rn = 5 then dPer end),
       R6    = max(case when sFlag =  'R' and rn = 6 then dPer end),
       aR1   = max(case when sFlag =  'R' and rn = 1 then dAmnt end),
       aR2   = max(case when sFlag =  'R' and rn = 2 then dAmnt end),
       aR3   = max(case when sFlag =  'R' and rn = 3 then dAmnt end),
       aR4   = max(case when sFlag =  'R' and rn = 4 then dAmnt end),
       aR5   = max(case when sFlag =  'R' and rn = 5 then dAmnt end),
       aR6   = max(case when sFlag =  'R' and rn = 6 then dAmnt end),
       O1    = max(case when sFlag <> 'R' and rn = 1 then dPer end),
       O2    = max(case when sFlag <> 'R' and rn = 2 then dPer end),
       O3    = max(case when sFlag <> 'R' and rn = 3 then dPer end),  
       aO1   = max(case when sFlag <> 'R' and rn = 1 then dAmnt end),
       aO2   = max(case when sFlag <> 'R' and rn = 2 then dAmnt end),
       aO3   = max(case when sFlag <> 'R' and rn = 3 then dAmnt end)
from   cte
group by sFlag
© www.soinside.com 2019 - 2024. All rights reserved.