我正在尝试进行行计算,以便将较大的值继续传送到后续行,直到比较较大的值为止。通过使用lag()函数将当前值与上一行进行比较来完成此操作。
代码
DECLARE @TAB TABLE (id varchar(1),d1 INT , d2 INT)
INSERT INTO @TAB (id,d1,d2)
VALUES ('A',0,5)
,('A',1,2)
,('A',2,4)
,('A',3,6)
,('B',0,4)
,('B',2,3)
,('B',3,2)
,('B',4,5)
SELECT id
,d1
,d2 = CASE WHEN id <> (LAG(id,1,0) OVER (ORDER BY id,d1)) THEN d2
WHEN d2 < (LAG(d2,1,0) OVER (ORDER BY id,d1)) THEN (LAG(d2,1,0) OVER (ORDER BY id,d1))
ELSE d2 END
输出(为清楚起见添加了od2行)
+----+----+----+ +----+
| id | d1 | d2 | | od2|
+----+----+----+ +----+
| A | 0 | 5 | | 5 |
| A | 1 | 5 | | 2 |
| A | 2 | 4 | | 4 |
| A | 3 | 6 | | 6 |
| B | 0 | 4 | | 4 |
| B | 2 | 4 | | 3 |
| B | 3 | 3 | | 2 |
| B | 4 | 5 | | 5 |
+----+----+----+ +----+
从输出中可以看到,滞后函数引用的是上一行的原始值,而不是新值。反正有实现这一目标的方法吗?
所需的输出
+----+----+----+ +----+
| id | d1 | d2 | | od2|
+----+----+----+ +----+
| A | 0 | 5 | | 5 |
| A | 1 | 5 | | 2 |
| A | 2 | 5 | | 4 |
| A | 3 | 6 | | 6 |
| B | 0 | 4 | | 4 |
| B | 2 | 4 | | 3 |
| B | 3 | 4 | | 2 |
| B | 4 | 5 | | 5 |
+----+----+----+ +----+
答案 0 :(得分:2)
尝试一下:
SELECT id
,d1
,d2
,MAX(d2) OVER (PARTITION BY ID ORDER BY d1)
FROM @TAB
想法是使用MAX
获取每个分区从开始到当前行的最大值。
答案 1 :(得分:0)
感谢您提供DDL脚本和DML。
一种方法是使用递归cte,如下所示。 1.首先根据id,d1和d2对所有记录进行排名。 -> CTE块 2.使用递归cte并使用rnk = 1获取第一个元素 3.字段“ compared_val”将检查前一个rnk中的值,以查看该值是否大于现有值,如果可以,则将交换该值
DECLARE @TAB TABLE (id varchar(1),d1 INT , d2 INT)
INSERT INTO @TAB (id,d1,d2)
VALUES ('A',0,5)
,('A',1,2)
,('A',2,4)
,('A',3,6)
,('B',0,4)
,('B',2,3)
,('B',3,2)
,('B',4,5)
;with cte
as (select row_number() over(partition by id order by d1,d2) as rnk
,id,d1,d2
from @TAB
)
,data(rnk,id,d1,d2,compared_val)
as (select rnk,id,d1,d2,d2 as compared_val
from cte
where rnk=1
union all
select a.rnk,a.id,a.d1,a.d2,case when b.compared_val > a.d2 then
b.compared_val
else a.d2
end
from cte a
join data b
on a.id=b.id
and a.rnk=b.rnk+1
)
select * from data order by id,d1,d2