【问题标题】:Convert specific columns into rows in SQL将特定列转换为 SQL 中的行
【发布时间】:2021-05-11 04:13:50
【问题描述】:

此屏幕截图包含我的结果,我想通过将AMOUNT_BILLED_JANUARY 列转换为如下行来进一步转置此查询:

M_ACCOUNTCONTRACT Bill_Date Previous1 Previous2 Previous3
16959 2019-05-13 10670.75 8580.66 6927.59
16959 2019-04-09 8580.66 6927.59 8181.64
16959 2019-03-09 6927.59 8181.64 8751.67

【问题讨论】:

  • Pivot 文档可在 here 获得。请包括您的个人尝试以及为什么它不适合您。如果这些列名是动态的(Previous1PreviousN,其中N 不固定),那么您将需要“动态 SQL”,本网站上已有大量示例。还是只需要前三个?
  • 我只需要前三个。

标签: sql-server pivot rows col


【解决方案1】:

将您当前的查询移动到公用表表达式 (cte) 中,但将 row_number() 函数的返回值保留为整数。您可以使用整数值来获取前面的行。

样本数据

复制当前结果的开头,但添加了一列。

create table currentResult
(
  M_AccountContract int,
  Bill_Date date,
  Amount_Billed_January decimal(7,2),
  Row_Num nvarchar(15),
  Num int -- include the row_number() function as integer value
);

insert into currentResult (M_AccountContract, Bill_Date, Amount_Billed_January, Row_Num, Num) values
(16959, '2019-05-13', 10670.75, 'previous1', 1),
(16959, '2019-04-09',  8580.66, 'previous2', 2),
(16959, '2019-03-12',  6927.59, 'previous3', 3),
(16959, '2019-02-08',  8181.64, 'previous4', 4),
(16959, '2019-01-11',  8751.67, 'previous5', 5);
-- got lazy here, please post text instead of images next time ;)

解决方案

使用您当前的结果并将其与自身连接,以查找必须通过一些简单的数学 (c2.Num >= c1.Num and c2.Num < c1.Num + 3) 进行旋转的行组,并在每个组中生成一个新的行号 (PrevNum)。然后使用新的PrevNum 列旋转每个组。

with cte as
(
  -- current query with row_number() integer value goes here
  select *
  from currentResult
),
cte_prev3 as
(
  select c1.M_AccountContract,
         c1.Bill_Date,
         row_number() over(partition by c1.M_AccountContract, c1.Bill_Date order by c2.Num) as PrevNum,
         c2.Amount_Billed_January
  from cte c1
  left join cte c2
    on  c2.M_AccountContract = c1.M_AccountContract
    and c2.Num >= c1.Num
    and c2.Num <  c1.Num + 3
)
select piv.M_AccountContract,
       piv.Bill_Date,
       piv.[1] as Previous1,
       piv.[2] as Previous2,
       piv.[3] as Previous3
from cte_prev3 cp3
pivot (max(cp3.Amount_Billed_January) for cp3.PrevNum in ([1], [2], [3])) piv
order by piv.Bill_Date desc;

结果

null 值是有限样本数据的结果。

M_AccountContract  Bill_Date   Previous1  Previous2  Previous3
-----------------  ----------  ---------  ---------  ---------
16959              2019-05-13   10670.75    8580.66    6927.59
16959              2019-04-09    8580.66    6927.59    8181.64
16959              2019-03-12    6927.59    8181.64    8751.67
16959              2019-02-08    8181.64    8751.67       null
16959              2019-01-11    8751.67       null       null

Fiddle 以查看实际情况以及中间的cte_prev3 结果。

【讨论】:

  • 您可以只旋转原始的cte,因为您已经有一个行号
  • 是的,但它会在所有结算日期使用1, 2, 3, 4, 5, 6, ...,而不是在每个结算日期使用1, 2, 3。还是我错过了什么?
  • 对不起,我错过了额外的分区条款。但我只会删除原始的行号并使用新的来代替。在这里要多说一点,原始的行号是不确定的,所以我认为你可以教 OP
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-14
  • 2020-04-28
相关资源
最近更新 更多