SQL Server 填补了时间序列中的空白

问题描述

我在处理 sql 请求时遇到问题。

我有两个表,一个表示日期向量,另一个表示不同证券的价格时间序列:

日期:

DateId 日期
1 2021-01-01
2 2021-01-02
3 2021-01-03

时代系列:

SecurityId DateId
1 1 0.25
1 3 0.32
2 1 0.41
2 2 0.67

时间序列可能有间隙,例如在上表中,SecurityId=1 在 DateId=2 处没有任何行,SecurityId=2 在 DateId=3 处没有任何行。

我需要构建一个请求,用时间序列中的最后一个值填补空白。 导致所有证券和所有日期的值如下:

SecurityId DateId
1 1 0.25
1 2 0.25
1 3 0.32
2 1 0.41
2 2 0.67
2 3 0.67

我尝试开始用正确的连接匹配所有日期

 SELECT  * from [TimeSerie] px RIGHT JOIN Dates dt on dt.DateId = px.Dateid

不幸的是,这不起作用,因为 DateId 上的相等性总是存在匹配的安全性,所以我没有得到没有值的 TimeSeries 行。

我正在研究 sql Server 标准 2019,我的目标是基于单个查询解决方案(避免使用临时表或游标的过程)。

解决方法

您可以使用 cross join 生成行,然后使用 left join

select d.*,s.*,ts.value
from dates d cross join
     (select distinct securityid from timeseries) s left join
     (select ts.*,lead(ts.dateid) over (partition by securityid order by dateid) as next_dateid
      from timeseries ts
     ) ts
     on s.securityid = ts.securityid and
        d.dateid >= ts.dateid and
        (d.dateid < ts.next_dateid or ts.next_dateid is null);

这假设 dateid 是连续的,这似乎是一个合理的假设。

,

一种方法是使用 CTE 和窗口化的 COUNT 将数据分组,然后获取该组的 MAX 值:

--Sample data
WITH Dates AS(
    SELECT *
    FROM (VALUES(1,CONVERT(date,'2021-01-01')),(2,'2021-01-02')),(3,'2021-01-03')))D(DateID,[Date])),TimeSerie AS(
    SELECT *
    FROM (VALUES(1,1,0.25),(1,3,0.32),0.41),2,0.67))V(SecurityID,DateID,[Value])),--Solution
DateSeries AS(
    SELECT DISTINCT
           D.DateID,D.[Date],TS.SecurityID
    FROM Dates D
         CROSS JOIN TimeSerie TS),Groups AS(
    SELECT DS.SecurityID,DS.DateID,TS.[value],COUNT(TS.[Value]) OVER (PARTITION BY DS.SecurityID ORDER BY [Date]) AS Grp
    FROM DateSeries DS
         LEFT JOIN TimeSerie TS ON DS.SecurityID = TS.SecurityID
                               AND DS.DateID = TS.DateID)
SELECT G.SecurityID,G.DateID,MAX([Value]) OVER (PARTITION BY G.SecurityID,G.Grp) AS [Value]
FROM Groups G;