Как заменить нулевое значение значением из следующей строки
Мне нужна поддержка в моем коде запроса SQL. Я должен заменить нулевое значение в столбце ненулевым значением из следующей строки.
В качестве примера мы можем использовать этот код:
declare @value table (r# int, value varchar(15))
insert into @value ( r#, value ) values
(1, NULL ) ,
(2, 'January'),
(3, 'February' ),
(4, NULL ),
(5, 'March' ),
(6, NULL ),
(7, Null ),
(8, 'December' ),
(9, Null ),
(10, Null ),
(11, Null ),
(12, 'November' ),
(13, Null )
select * from @value
Когда я использую функцию отведения, я получаю это значение, но оно не работает с NULL. Что мне нужно, это получить:
1 January
2 January
3 February
4 March
5 March
6 December
7 December
8 December
9 November
10 November
11 November
12 November
13 NULL
Бу из моего запроса:
SELECT r#,
value
,case when value is null then Lead(value) OVER ( order by r# asc) else value end as RESULT
FROM @value
order by r#
У меня есть: ![enter image description here]()
Ответы
Ответ 1
Вы можете сделать это с помощью оконных функций. К сожалению, SQL Server не поддерживает параметр IGNORE NULL
в LEAD()
, поэтому это не вариант.
Однако вы можете использовать два уровня оконных функций:
select v.r#, v.value,
coalesce(v.value, max(value) over (partition by next_r#)) as imputed_value
from (select v.*,
min(case when value is not null then r# end) over (order by r# desc) as next_r#
from @value v
) v
order by v.r#;
На 13 рядах разница в производительности, вероятно, не заметна. Тем не менее, это должно иметь гораздо лучшую производительность по мере увеличения числа строк.
Ответ 2
Следующий подход может помочь. Вам нужен дополнительный оператор APPLY
чтобы найти первую запись со значением, NULL
:
T-SQL:
SELECT
v1.[r#],
CASE
WHEN v1.[value] IS NULL THEN v2.[value]
ELSE v1.[value]
END AS [value]
FROM @value v1
OUTER APPLY (
SELECT TOP 1 [Value]
FROM @value
WHERE (v1.[r#] < [r#]) AND [value] IS NOT NULL
) v2
Выход:
r# value
1 January
2 January
3 February
4 March
5 March
6 December
7 December
8 December
9 November
10 November
11 November
12 November
13 NULL
Ответ 3
Вы можете попробовать ниже SQL-кода, используя сопутствующий подзапрос
SELECT v1.r#,CASE WHEN value IS NOT NULL THEN v1.Value
ELSE ( SELECT TOP 1 value
FROM @value v2
WHERE v2.r# > v1.r# AND v2.[value] IS NOT NULL
) END Value
FROM @value v1
ИЛИ (без указания случая)
SELECT v1.r#,ISNULL(v1.VALUE,( SELECT TOP 1 value
FROM @value v2
WHERE v2.r# > v1.r#
AND v2.[value] IS NOT NULL
)
) AS [MonthNames]
FROM @value v1
Результат
r# Value
----------
1 January
2 January
3 February
4 March
5 March
6 December
7 December
8 December
9 November
10 November
11 November
12 November
13 NULL
Ответ 4
следующий запрос работает в SQL Server:
;WITH CTE_Value
AS (
SELECT R#, Value
FROM @value AS T
WHERE Value IS NOT NULL
UNION ALL
SELECT t.r#, c.Value
FROM @value AS t
INNER JOIN CTE_Value AS c ON t.r# + 1 = c.r#
WHERE t.Value IS NULL
)
SELECT *
FROM CTE_Value
UNION ALL
SELECT v.*
FROM @value AS v
LEFT JOIN CTE_value AS c ON v.r# = c.r#
WHERE c.r# IS NULL
ORDER BY r#