繁体   English   中英

Sql查询根据不同的场景为来自其他行的具有空值的列赋值

[英]Sql query to assign value to a column having null value from other row based on different scenarios

我有以下真实的生产数据场景,我正在尝试获得所需的输出。 我必须从其他行(基于数据的下一个或上一个)填充 Worker 的所有 NULL 值。

样本输入

PK  Id  Status      Worker      Created Date
--- --- ----------- ----------- -------------
1   101 Waiting     NULL        1/1/2019 8:00
2   101 Assigned    Jon Doe     1/1/2019 8:10
3   101 Initiated   Jon Doe     1/1/2019 8:15    
4   102 Waiting     NULL        1/1/2019 8:00
5   102 Waiting     NULL        1/1/2019 8:12
6   102 Assigned    Jane Doe    1/1/2019 8:15
7   103 Waiting     NULL        1/1/2019 8:00
9   103 Initiated   Jon Doe     1/1/2019 8:15
11  103 Waiting     NULL        1/1/2019 8:17
12  103 Assigned    Jane Doe    1/1/2019 8:20
13  103 Assigned    NULL        1/1/2019 8:22
14  103 Initiated   NULL        1/1/2019 8:25

期望输出

PK  Id  Status      Worker      Created Date
--- --- ----------- ----------- -------------
1   101 Waiting     Jon Doe     1/1/2019 8:00
2   101 Assigned    Jon Doe     1/1/2019 8:10
3   101 Initiated   Jon Doe     1/1/2019 8:15    
4   102 Waiting     Jane Doe    1/1/2019 8:00
5   102 Waiting     Jane Doe    1/1/2019 8:12
6   102 Assigned    Jane Doe    1/1/2019 8:15
7   103 Waiting     Jon Doe     1/1/2019 8:00
9   103 Initiated   Jon Doe     1/1/2019 8:15
11  103 Waiting     Jane Doe    1/1/2019 8:17
12  103 Assigned    Jane Doe    1/1/2019 8:20
13  103 Assigned    Jane Doe    1/1/2019 8:22
14  103 Initiated   Jane Doe    1/1/2019 8:25

查询语句:

select tl.*, RANK() OVER (ORDER BY tl.[Id],tl.[Created Date]) rnk 
into #temp 
from table tl

select tl.*, 
       case when tl.[Worker] is null t2.[Worker] else tl.[Worker] end as [Worker Updated]
from #temp tl
left join #temp t2 on tl.[Id]=t2.[Id] and tl.rnk=t2.rnk-1

我只能在输入数据样本中获得场景 ID 101 的正确结果。 我不确定如何处理场景 102(在 Worker 列上连续两行具有 NULL)和 103(在 Worker 上具有 NULL 的最后 2 行)。

有人可以帮我吗?

我认为你需要的是ISNULL()MAX() OVER()所以你的查询会是这样的:

SELECT  
    t1.PK
,   t1.Id
,   t1.Status
,   ISNULL(t1.Worker, MAX(t1.Worker) OVER(PARTITION BY Id) ) Worker
,   t1.CreatedDate
FROM #temp tl

ISNULL() 将检查该值,如果它为 null 将用辅助值替换它。 这与您在查询中遇到的情况相同。

MAX(t1.Worker) OVER(PARTITION BY Id)

由于聚合函数消除了空值,我们利用这一优势并将其与OVER()子句一起使用,以按Id对行进行分区,并使用聚合函数之一获取我们需要的值。

可能最简单的方法是outer apply

select t.id, t.status, t2.worker, t.date
from t outer apply
     (select top (1) t2.*
      from t2
      where t2.worker is not null and t2.id >= t.id
      order by t2.id asc
     ) t2;

您真正想要的是LEAD()上的IGNORE NULLS选项。 但是,SQL Server 不支持。

如果你想用前面的值填充最近的值,那么用另一个apply遵循相同的逻辑:

select t.id, t.status,
       coalesce(tnext.worker, tprev.worker) as worker, t.date
from t outer apply
     (select top (1) t2.*
      from t2
      where t2.worker is not null and t2.id >= t.id
      order by t2.id asc
     ) tnext outer apply
     (select top (1) t2.*
      from t2
      where t2.worker is not null and t2.id <= t.id
      order by t2.id desc
     ) tprev;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM