我正在使用LAG函数将我的值向下移动一行。
但是,如果源列中的项目重复,则需要使用与以前相同的值:
ID | SOURCE | LAG | DESIRED OUTCOME
1 | 4 | - | -
2 | 2 | 4 | 4
3 | 3 | 2 | 2
4 | 3 | 3 | 2
5 | 3 | 3 | 2
6 | 1 | 3 | 3
7 | 4 | 1 | 1
8 | 4 | 4 | 1
如您所见,例如在ID范围3-5中,源数据不会更改,并且期望的结果应该从最后一行以不同的值进行馈送(因此,在这种情况下, ID 2 >)。
答案 0 :(得分:0)
Sql服务器的lag版本在第二个参数中支持一个表达式,以确定返回多少行。您可以用某种支票取代它,例如不要回首
select lagged = lag(data,iif(decider < 0,0,1)) over (order by id)
from (values(0,1,'dog')
,(1,2,'horse')
,(2,-1,'donkey')
,(3,2,'chicken')
,(4,23,'cow'))f(id,decider,data)
这将返回以下列表
null
dog
donkey
donkey
chicken
因为decider
为2的行中的id
值为负。
答案 1 :(得分:0)
好吧,第一延迟可能不是完成任务的工具。使用递归CTE可能更容易解决。 SQL和窗口函数在集合上工作。也就是说,我们的目标是提出一种描述我们想要的方法。我们希望对数据进行分区,以使具有相同值的顺序岛成为同一集合的一部分。
我们可以做到这一点的一种方法是使用lag
帮助我们发现上一行是否不同。
从那里,我们现在可以对这些更改事件进行累加,以创建分区。一旦有了分区,就可以为分区中的每个元素分配一个行号。最后,有了这些代码后,我们现在就可以使用行号来查找
支持这么多元素。
;with d as (
select * from (values
(1,4)
,(2,2)
,(3,3)
,(4,3)
,(5,3)
,(6,1)
,(7,4)
,(8,4)
)f(id,source))
select *,lag(source,rn) over (order by Id)
from (
select *,rn=row_number() over (partition by partition_id order by id)
from (
select *, partition_id = sum(change) over (order by id)
from (
select *,change = iif(lag(source) over (order by id) != source,1,0)
from d
) source_with_change
) partitioned
) row_counted
顺便说一句,这个绝对残酷的面试问题被要求我做一次。