如果行中的后续值重复,如何使用LAG函数并返回相同的值?

时间:2019-05-23 21:30:25

标签: sql-server

我正在使用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 >)。

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

顺便说一句,这个绝对残酷的面试问题被要求我做一次。