一尘不染

如何使LAG()在SQL Server中忽略NULL?

sql

有谁知道如何用字符串替换列中的空值,直到命中新的字符串,然后该字符串替换其下的所有空值?我有一个看起来像这样的专栏

原始专栏:

PAST_DUE_COL           
91 or more days pastdue        
Null
Null
61-90 days past due          
Null
Null
31-60 days past due
Null
0-30 days past due
Null       
Null
Null

预期结果列:

PAST_DUE_COL           
91 or more days past due        
91 or more days past due
91 or more days past due
61-90 days past due          
61-90 days past due 
61-90 days past due 
31-60 days past due
31-60 days past due
0-30 days past due
0-30 days past due      
0-30 days past due
0-30 days past due

本质上,我希望列中的第一个字符串替换它下面的所有空值,直到下一个字符串为止。然后,该字符串将替换其下的所有null,直到下一个字符串,依此类推。


阅读 241

收藏
2021-05-23

共1个答案

一尘不染

SQL Server不支持ignore nulls窗口功能(例如lead()和)的选项lag(),对此问题非常适合。

我们可以通过一些差距和孤岛技术来解决此问题:

select
    t.*,
    max(past_due_col) over(partition by grp) new_past_due_col
from (
    select 
        t.*,
        sum(case when past_due_col is null then 0 else 1 end)
            over(order by id) grp
    from mytable t
) t

子查询执行的窗口总和每次发现非null值时都会递增:这定义了包含非null值后跟null值的行组。

然后,外部使用窗口max()检索每个组中的(仅)非null值。

假设可以使用一列对记录进行 排序 (我称之为id)。

DB
Fiddle上的演示

ID | PAST_DUE_COL            | grp | new_past_due_col       
-: | :---------------------- | --: | :----------------------
 1 | 91 or more days pastdue |   1 | 91 or more days pastdue
 2 | null                    |   1 | 91 or more days pastdue
 3 | null                    |   1 | 91 or more days pastdue
 4 | 61-90 days past due     |   2 | 61-90 days past due    
 5 | null                    |   2 | 61-90 days past due    
 6 | null                    |   2 | 61-90 days past due    
 7 | 31-60 days past due     |   3 | 31-60 days past due    
 8 | null                    |   3 | 31-60 days past due    
 9 | 0-30 days past due      |   4 | 0-30 days past due     
10 | null                    |   4 | 0-30 days past due     
11 | null                    |   4 | 0-30 days past due     
12 | null                    |   4 | 0-30 days past due     
2021-05-23