我有以下实际生产数据场景,我正在尝试获得所需的输出。我必须从其他行(基于数据的下一个或上一个)中填充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
SQL:
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)。
有人可以帮我吗?
答案 0 :(得分:1)
我认为您需要的是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
对行进行分区,并使用其中一个聚合函数获得所需的值。
答案 1 :(得分:0)
可能最简单的方法是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;
您真正想要的是IGNORE NULLS
上的LEAD()
选项。但是,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;