如何告诉LAG函数获取最后一个“非空”值?
例如,请参阅下面的表格,其中我在B列和C列上有一些NULL值。 我想用最后一个非空值填充空值。我试图通过使用LAG函数来做到这一点,如下所示:
case when B is null then lag (B) over (order by idx) else B end as B,
但是当我在一行中有两个或多个空值时,这并不常用(请参阅C列第3行的NULL值 - 我希望它是原始的0.50。)
知道如何实现这一目标? (它不必使用LAG功能,欢迎任何其他想法)
一些假设:
由于
答案 0 :(得分:6)
您可以使用outer apply
运算符
select t.id,
t1.colA,
t2.colB,
t3.colC
from table t
outer apply(select top 1 colA from table where id <= t.id and colA is not null order by id desc) t1
outer apply(select top 1 colB from table where id <= t.id and colB is not null order by id desc) t2
outer apply(select top 1 colC from table where id <= t.id and colC is not null order by id desc) t3;
这将起作用,无论空值的数量或空“孤岛”。您可能有值,然后是空值,然后是值,再次为空。它仍然有效。
但是,假设(在您的问题中)假设:
我有一个
NULL
后,NULL
一直到最后 - 所以我想用最新的值填充它。
有一个更有效的解决方案。我们只需要找到最新的(按idx
排序)值。修改上述查询,从子查询中删除where id <= t.id
:
select t.id,
colA = coalesce(t.colA, t1.colA),
colB = coalesce(t.colB, t2.colB),
colC = coalesce(t.colC, t3.colC)
from table t
outer apply (select top 1 colA from table
where colA is not null order by id desc) t1
outer apply (select top 1 colB from table
where colB is not null order by id desc) t2
outer apply (select top 1 colC from table
where colC is not null order by id desc) t3;
答案 1 :(得分:4)
您可以对ORDER BY
进行更改,以强制NULL在您的订购中排在第一位,但这可能很昂贵......
lag(B) over (order by CASE WHEN B IS NULL THEN -1 ELSE idx END)
或者,使用子查询计算一次替换值。在较大的套装上可能更便宜,但非常笨重 - 依赖于最后的所有NULL - LAG不依赖于
COALESCE(
B,
(
SELECT
sorted_not_null.B
FROM
(
SELECT
table.B,
ROW_NUMBER() OVER (ORDER BY table.idx DESC) AS row_id
FROM
table
WHERE
table.B IS NOT NULL
)
sorted_not_null
WHERE
sorted_not_null.row_id = 1
)
)
(对于较大的数据集,这应该比LAG
或使用带有相关子查询的OUTER APPLY
更快,因为该值只计算一次。为了整洁,您可以计算并为变量中的每一列存储[last_known_value],然后只使用COALESCE(A, @last_known_A), COALESCE(B, @last_known_B), etc
)
答案 2 :(得分:1)
如果它一直为空,那么可以采取捷径
declare @b varchar(20) = (select top 1 b from table where b is not null order by id desc);
declare @c varchar(20) = (select top 1 c from table where c is not null order by id desc);
select is, isnull(b,@b) as b, insull(c,@c) as c
from table;
答案 3 :(得分:1)
Select max(diff) from(
Select
Case when lag(a) over (order by b) is not null
Then (a -lag(a) over (order by b)) end as diff
From <tbl_name> where
<relevant conditions>
Order by b) k
在 db 可视化工具中工作正常。
答案 4 :(得分:-3)
UPDATE table
SET B = (@n := COALESCE(B , @n))
WHERE B is null;