Tôi có đầu vào sau:
id | value
----+-------
1 | 136
2 | NULL
3 | 650
4 | NULL
5 | NULL
6 | NULL
7 | 954
8 | NULL
9 | 104
10 | NULL
Tôi mong đợi kết quả sau:
id | value
----+-------
1 | 136
2 | 136
3 | 650
4 | 650
5 | 650
6 | 650
7 | 954
8 | 954
9 | 104
10 | 104
Giải pháp tầm thường sẽ là nối các bảng với một <
mối quan hệ và sau đó chọn MAX
giá trị trong 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;
Tuy nhiên, việc thực thi tầm thường của mã này sẽ tạo ra bên trong bình phương số đếm của các hàng của bảng đầu vào ( O (n ^ 2) ). Tôi mong đợi t-sql sẽ tối ưu hóa nó - ở cấp độ khối / bản ghi, công việc phải làm là rất dễ dàng và tuyến tính, về cơ bản là một vòng lặp for ( O (n) ).
Tuy nhiên, trong các thử nghiệm của tôi, MS SQL 2016 mới nhất không thể tối ưu hóa chính xác truy vấn này, khiến cho truy vấn này không thể thực thi đối với bảng đầu vào lớn.
Hơn nữa, truy vấn phải chạy nhanh, làm cho một giải pháp dựa trên con trỏ dễ dàng tương tự (nhưng rất khác nhau) không khả thi.
Sử dụng một số bảng tạm thời được hỗ trợ bộ nhớ có thể là một sự thỏa hiệp tốt, nhưng tôi không chắc liệu nó có thể được chạy nhanh hơn đáng kể hay không, xem xét rằng truy vấn ví dụ của tôi sử dụng các truy vấn con không hoạt động.
Tôi cũng đang suy nghĩ để khai thác một số chức năng cửa sổ từ các tài liệu t-sql, những gì có thể bị lừa để làm những gì tôi muốn. Ví dụ: tổng tích lũy đang thực hiện một số tương tự, nhưng tôi không thể lừa nó để đưa ra phần tử không null mới nhất và không phải là tổng của các phần tử trước đó.
Giải pháp lý tưởng sẽ là một truy vấn nhanh mà không cần mã thủ tục hoặc bảng tạm thời. Ngoài ra, một giải pháp với các bảng tạm thời là được, nhưng lặp lại quy trình bảng thì không.