如果前一个数字为 0,则如何使用 LAG 语法取上个月的数字

How to take the previous number if it is 0 then take the previous month's number using LAG syntax

提问人:Arif 提问时间:9/28/2023 最后编辑:Dale KArif 更新时间:9/28/2023 访问量:94

问:

enter image description here

源数据 :

Account Period  Amount
AC100   January 100
AC100   February    0
AC100   March   0
AC100   April   0
AC100   May 0
AC100   June    600
AC100   July    700
AC100   August  0
AC100   September   0
AC100   October 1000
AC100   November    0
AC100   December    1200

我使用这个查询

WITH CTE AS (
    SELECT
        Account,
        Period,
        Amount,
        LAG(Amount, 1, 0) OVER (PARTITION BY Account ORDER BY (SELECT NULL)) AS PreviousAmount
    FROM TableA
)
SELECT
    Account,
    Period,
    CASE WHEN Amount = 0 THEN PreviousAmount ELSE Amount END AS Amount
FROM CTE

但结果仅取上个月的金额,如下图所示:

enter image description here

如何确保金额 0 保持填充前一个数字?

sql-server 滞后 间隙和孤岛 sql-server-2019

评论

2赞 Thom A 9/28/2023
提问时,请不要上传代码/数据/错误的图片。
2赞 Thom A 9/28/2023
如果你在 2022 年,这要简单一些,因为实现了 .您使用的是什么版本?IGNORE NULLS
1赞 Arif 9/28/2023
@ThomA我全年都在使用
1赞 shawnt00 9/28/2023
值总是升序的吗?如果是这样,您只想要最大值。
1赞 Dale K 9/28/2023
你熟悉当有人回答时该怎么做吗?

答:

-1赞 3N1GM4 9/28/2023 #1

使用示例数据:

create table #data
(
    Account varchar(5),
    [Period] varchar(9),
    amount int
)

insert into #data values
('AC100','January',100),
('AC100','February',0),
('AC100','March',0),
('AC100','April',0),
('AC100','May',0),
('AC100','June',600),
('AC100','July',700),
('AC100','August',0),
('AC100','September',0),
('AC100','October',1000),
('AC100','November',0),
('AC100','December',1200)

为此,您可以找到最后一个非零值,并在值为零时返回该值:OUTER APPLYamountamount

select
    d.Account,
    d.[Period],
    case when d.amount = 0 then lastNum.lastAmount else d.amount end as amount
from #data d
outer apply
(
    select top 1 amount as lastAmount
    from #data l
    where month(l.[Period] + '1 1900') < month(d.[Period] + '1 1900')
    and l.amount <> 0
    order by month(l.[Period] + '1 1900') desc
) lastNum

结果:

帐户 时期
AC100系列 一月 100
AC100系列 二月 100
AC100系列 三月 100
AC100系列 四月 100
AC100系列 五月 100
AC100系列 六月 600
AC100系列 七月 700
AC100系列 八月 700
AC100系列 九月 700
AC100系列 十月 1000
AC100系列 十一月 1000
AC100系列 十二月 1200

评论

2赞 Jonas Metzler 9/28/2023
@Arif 当答案对您有帮助时,请不要在评论中写“谢谢”。您可以通过单击左侧的复选标记来对答案投赞成票和/或接受它作为支持您的问题的答案(最后一个选项只能用于一个答案)。
1赞 SelVazi 9/28/2023 #2

这是一个间隙和孤岛问题,您可以使用窗口函数来解决它来计算运行总数,这将创建具有连续月份的行具有相同 rn 值的孤岛。sum()

窗口函数,用于查找每个账户在每个岛屿内的最大金额。max()

with cte as (
  select *, sum(Amount) over (partition by Account order by MONTH(Period + ' 1 2014') ) as rn
  from TableA
)
select Account, Period, max(Amount) over (partition by Account, rn ) as Amount
from cte

结果:

Account Period    Amount
AC100   January   100
AC100   February  100
AC100   March     100
AC100   April     100
AC100   May       100
AC100   june      600
AC100   july      700
AC100   August    700
AC100   September 700
AC100   October   1000
AC100   November  1000
AC100   December  1200

在这里演示