我有一个表,其中包含时间序列数据,大多数为null,我想用最后一个已知值填充所有null。
我有一些解决方案,但是它们比在Pandas中执行等效的DataFrame.fillna(method='ffill')
操作要慢得多。
我正在使用的代码/数据的简化版本:
select d.[date], d.[price],
(select top 1 p.price from price_table p
where p.price is not null and p.[date] <= p.[date]
order by p.[date] desc) as ff_price
from price_table d
产生表格
date price ff_price
---------- ----- --------
2016-07-11 0.79 0.79
2016-07-12 NULL 0.79
2016-07-13 NULL 0.79
2016-07-14 0.69 0.69
2016-07-15 NULL 0.69
...
2016-09-21 0.88 0.88
...
我有1亿多行,所以要花很长时间。
答案 0 :(得分:2)
这看起来像一个“经典”的鸿沟和孤岛问题。 假设您没有使用2008年或更早的版本(它们(几乎)全部不在支持范围内),则应该为您提供您所追求的结果:
WITH CTE AS(
SELECT [date],
price,
COUNT(CASE WHEN price IS NOT NULL THEN 1 END) OVER (ORDER BY [date]
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS Grp
FROM price_table p)
SELECT [date],
price,
MIN(price) OVER (PARTITION BY grp) AS ff_price
FROM CTE;
答案 1 :(得分:1)
您也可以使用APPLY
:
SELECT t.*, t1.price AS ff_price
FROM price_table t OUTER APPLY
(SELECT TOP (1) t1.*
FROM price_table t1
WHERE t1.[date] <= t.[date] AND t1.price IS NOT NULL
ORDER BY t1.[date] DESC
) t1;
答案 2 :(得分:1)
假设您的列为DATE
,价格为DECIMAL(5,2)
,请测试此方法:
SELECT
P.[date],
P.[price],
ff_price = CONVERT(
DECIMAL(5,2), -- Original price datatype
SUBSTRING(
MAX(
CAST(P.[date] AS BINARY(3)) + -- 3: datalength of P.[date] column
CAST(P.[price] AS BINARY(5)) -- 5: datalength of P.[price] column
) OVER (ORDER BY P.[date] ROWS UNBOUNDED PRECEDING),
4, -- Position to start that's not the binary part of the date
5))-- Characters that compose the binary of the original price datatype
FROM
price_table AS P
这是我为解决类似问题而实施的解决方案,您可以找到详尽的解释here。这种方法之所以好,是因为只要您有date
的索引, 它就不需要显式排序 。
它的作用基本上是使用带窗口的MAX
和由3个字节组成的日期列的串联(这就是为什么我提到您的列必须为DATE
,否则为{{1} }将需要8个字节,您可以编辑查询以对此进行处理),其中包含构成价格列的字节(也假定为5个字节)。这是DATETIME
部分。
当您计算此值和CAST(P.[date] AS BINARY(3)) + CAST(P.[price] AS BINARY(5))
时,引擎基本上会使用最大有效字节是您的日期的值进行最大滚动。当日期更改时,最大结果将始终更新,但考虑到将任何值与ORDER BY P.[date] ROWS UNBOUNDED PRECEDING
连接起来也将产生NULL
(作为二进制),那么NULL
将始终忽略此值并保留前一个非空的MAX
(由MAX
保留)。
这是窗口P.[date] ROWS UNBOUNDED PRECEDING
的二进制结果(我添加了MAX
的前一条记录,因此对于空价格值,您看到的结果是NULL
)
NULL