我有一个空值的时间序列。我想用最新的非非值替换每个空值。根据我的研究,Oracle SQL可以使用Last_value和IGNORE NULLS轻松完成此任务。有没有类似的方法来使用SQL Server 2016实现这一目标?否则我只是想用C#编写代码,但感觉使用SQL会更快,更干净,更容易。
Sec SCORE
1 Null
2 Null
3 5
4 Null
5 8
6 7
7 Null
应替换为:
Sec SCORE
1 Null
2 Null
3 5
4 5
5 8
6 7
7 7
答案 0 :(得分:5)
您可以通过两次累积操作来完成此操作:
select t.*,
coalesce(score, max(score) over (partition by id)) as newscore
from (select t.*,
max(case when score is not null then id end) over (order by id) as maxid
from t
) t;
最里面的子查询获取有值的最新id。最外面的一个“将”值“扩展”到后续行。
如果您确实想要更新表格,可以轻松地将其合并到update
中。但是,Oracle不能(轻松)做到这一点,所以我猜这不是必要的。
答案 1 :(得分:3)
如果性能是一个问题,我建议本文提供解决方案:
他的最终解决方案虽然密集,但在没有任何联接的线性查询计划下确实表现出色。这是我使用的示例实现,该实现通过type2 scd登台表携带了最后一个客户名称。在此登台表中,NULL表示不进行更新,而'*** DELETED ***'
表示显式设置为NULL。以下内容将其清理得非常类似于实际的SCD记录:
WITH [SampleNumbered] AS (
SELECT *, ROW_NUMBER() OVER ( PARTITION BY [SampleId] ORDER BY [StartDatetime] ) AS [RowNumber]
FROM [dbo].[SampleDimStage]
), [SamplePrep] AS (
SELECT [SampleId]
, [StartDatetime]
, CAST([RowNumber] AS BINARY(8)) + CAST([SampleGroupId] AS VARBINARY(255)) AS [BinarySampleGroupId]
, CAST([RowNumber] AS BINARY(8)) + CAST([SampleStatusCode] AS VARBINARY(255)) AS [BinarySampleStatusCode]
FROM [SampleNumbered]
), [SampleCleanUp] AS (
SELECT [SampleId]
, [StartDatetime]
, CAST(SUBSTRING(MAX([BinarySampleGroupId]) OVER( PARTITION BY [SampleId] ORDER BY [StartDatetime] )
, 9, 255) AS VARCHAR(255)) AS [LastSampleGroupId]
, CAST(SUBSTRING(MAX([BinarySampleStatusCode]) OVER( PARTITION BY [SampleId] ORDER BY [StartDatetime] )
, 9, 255) AS VARCHAR(255)) AS [LastSampleStatusCode]
, LEAD([StartDatetime]) OVER( PARTITION BY [SampleId] ORDER BY [StartDatetime] ) AS [EndDatetime]
FROM [SamplePrep]
)
SELECT CAST([SampleId] AS NUMERIC(18)) AS [SampleId]
, CAST(NULLIF([sc].[LastSampleGroupId],'*** DELETED ***') AS NUMERIC(18)) AS [GroupId]
, CAST(NULLIF([sc].[LastSampleStatusCode],'*** DELETED ***') AS CHAR(3)) AS [SampleStatusCode]
, [StartDatetime]
, [sc].[EndDatetime]
FROM [SampleCleanUp] [sc];
如果您的排序键是某种整数,则可以完全跳过第一个CTE并将其直接转换为二进制。