LAG功能和NULLS

时间:2016-04-25 10:28:50

标签: sql sql-server tsql sql-server-2016

如何告诉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功能,欢迎任何其他想法)

一些假设:

  • 行数是动态的;
  • 第一个值将始终为非null;
  • 一旦我有一个NULL,就是NULL一直到最后 - 所以我想用最新的值填充它。

由于

enter image description here

5 个答案:

答案 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;