我有以下输入:
id | value
----+-------
1 | 136
2 | NULL
3 | 650
4 | NULL
5 | NULL
6 | NULL
7 | 954
8 | NULL
9 | 104
10 | NULL
我期望得到以下结果:
id | value
----+-------
1 | 136
2 | 136
3 | 650
4 | 650
5 | 650
6 | 650
7 | 954
8 | 954
9 | 104
10 | 104
简单的解决方案是将表与一个<
关系连接起来,然后在中选择一个MAX
值GROUP BY
:
WITH tmp AS (
SELECT t2.id, MAX(t1.id) AS lastKnownId
FROM t t1, t t2
WHERE
t1.value IS NOT NULL
AND
t2.id >= t1.id
GROUP BY t2.id
)
SELECT
tmp.id, t.value
FROM t, tmp
WHERE t.id = tmp.lastKnownId;
但是,此代码的琐碎执行将在内部创建输入表的行数的平方(O(n ^ 2))。我期望t-sql可以优化它-在块/记录级别,要做的任务非常简单且线性,本质上是for循环(O(n))。
但是,在我的实验中,最新的MS SQL 2016无法正确优化此查询,因此无法对大型输入表执行此查询。
此外,查询必须快速运行,使得基于游标的类似的简单(但非常不同)解决方案不可行。
使用一些由内存支持的临时表可能是一个不错的折衷方案,但是我不确定它是否可以以更快的速度运行,因为考虑到我的使用子查询的示例查询无法正常工作。
我也在考虑从t-sql文档中挖掘出一些窗口函数,可以骗我做什么。例如,累加总和在做一些非常相似的事情,但是我不能欺骗它给出最新的非null元素,而不是以前的元素之和。
理想的解决方案是没有程序代码或临时表的快速查询。另外,使用临时表的解决方案也可以,但按程序迭代表则不行。