用给定分区内的前一个非空值替换 NULL 值
Replace NULL value with previous not null one within given partition
如何计算新列,其中 Number
列的 NULL
值将替换为先前的非空值?不是 NULL
的应该保持不变。全部在 Customer
.
的分区内
+----------+------------+--------+
| Customer | Date | Number |
+----------+------------+--------+
| A | 2016-01-01 | 9,00 |
| A | 2020-01-01 | NULL |
| A | 2020-01-15 | 10,00 |
| A | 2020-02-01 | NULL |
| A | 2020-03-01 | NULL |
| A | 2020-03-15 | 11,00 |
| A | 2020-04-01 | NULL |
| B | 2016-01-01 | 9,00 |
| B | 2020-01-01 | NULL |
| B | 2020-01-15 | 10,00 |
| B | 2020-02-01 | NULL |
| B | 2020-03-01 | NULL |
| B | 2020-03-15 | 11,00 |
| B | 2020-04-01 | NULL |
+----------+------------+--------+
假设:
- 输入数据是
ORDER BY Customer, Date
,输出数据也是如此
- 每个
Customer
的第一行(最旧的行)总是有 Number
不同于 NULL
如果 SQL 服务器支持 lag(ignore nulls)
,这会更容易。但事实并非如此。您可以通过对具有值的行进行累积计数然后散布这些值来定义组:
select t.*,
max(number) over (partition by customer, grp)
from (select t.*, count(number) over (partition by customer order by date) as grp
from t
) t;
您也可以使用 apply
执行此操作,但我怀疑上面的方法几乎在所有情况下都更快。
SELECT customer ,[date] ,case when number is null then B.number else t.number end number
FROM yourTable t
CROSS APPLY (
SELECT TOP 1 number
FROM yourTable
WHERE customer = t.customer
AND number IS NOT NULL
ORDER BY DATE DESC
) B
如何计算新列,其中 Number
列的 NULL
值将替换为先前的非空值?不是 NULL
的应该保持不变。全部在 Customer
.
+----------+------------+--------+
| Customer | Date | Number |
+----------+------------+--------+
| A | 2016-01-01 | 9,00 |
| A | 2020-01-01 | NULL |
| A | 2020-01-15 | 10,00 |
| A | 2020-02-01 | NULL |
| A | 2020-03-01 | NULL |
| A | 2020-03-15 | 11,00 |
| A | 2020-04-01 | NULL |
| B | 2016-01-01 | 9,00 |
| B | 2020-01-01 | NULL |
| B | 2020-01-15 | 10,00 |
| B | 2020-02-01 | NULL |
| B | 2020-03-01 | NULL |
| B | 2020-03-15 | 11,00 |
| B | 2020-04-01 | NULL |
+----------+------------+--------+
假设:
- 输入数据是
ORDER BY Customer, Date
,输出数据也是如此 - 每个
Customer
的第一行(最旧的行)总是有Number
不同于NULL
如果 SQL 服务器支持 lag(ignore nulls)
,这会更容易。但事实并非如此。您可以通过对具有值的行进行累积计数然后散布这些值来定义组:
select t.*,
max(number) over (partition by customer, grp)
from (select t.*, count(number) over (partition by customer order by date) as grp
from t
) t;
您也可以使用 apply
执行此操作,但我怀疑上面的方法几乎在所有情况下都更快。
SELECT customer ,[date] ,case when number is null then B.number else t.number end number
FROM yourTable t
CROSS APPLY (
SELECT TOP 1 number
FROM yourTable
WHERE customer = t.customer
AND number IS NOT NULL
ORDER BY DATE DESC
) B