다음과 같은 입력이 있습니다.
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이 아닌 요소를 제공하도록 속일 수는 없었습니다.
이상적인 솔루션은 절차 코드 나 임시 테이블이없는 빠른 쿼리입니다. 또는 임시 테이블이있는 솔루션은 괜찮지 만 절차 적으로 테이블을 반복하는 것은 아닙니다.