用SQL Server中以前的非零值填充零值

用SQL Server中以前的非零值填充零值,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我试图用之前给定的股息数据填充所有行的零值。如何使用先前给定的红利填充零值,以及如何对MS SQL server中的所有给定行进行填充 如何使用SELECT命令而不使用UPDATE命令执行此操作 Date | ticker| dividends| 2019/01/24| AAPL | 0| 2019/01/23| AAPL | 0| 2019/01/22| AAPL | 0| 2019/01/21| AAPL |

我试图用之前给定的股息数据填充所有行的零值。如何使用先前给定的红利填充零值,以及如何对MS SQL server中的所有给定行进行填充

如何使用SELECT命令而不使用UPDATE命令执行此操作

Date      | ticker| dividends|
2019/01/24| AAPL |          0| 
2019/01/23| AAPL |          0|        
2019/01/22| AAPL |          0| 
2019/01/21| AAPL |       0.77|
2019/01/20| AAPL |          0|       
2019/01/19| AAPL |          0|       
2019/01/18| AAPL |          0|       
2019/01/17| AAPL |       0.82| 
....
....

**OUTPUT**
Date      | ticker| dividends|
2019/01/24| AAPL |       0.77| 
2019/01/23| AAPL |       0.77|        
2019/01/22| AAPL |       0.77| 
2019/01/21| AAPL |       0.77|
2019/01/20| AAPL |       0.82|       
2019/01/19| AAPL |       0.82|       
2019/01/18| AAPL |       0.82|       
2019/01/17| AAPL |       0.82| 
....
....
编辑:由于要计算select语句中的值,因此有一种方法:

SELECT *
FROM tbl t1
CROSS APPLY (
    SELECT TOP 1 t2.dividends AS nonzero_dividends
    FROM tbl t2 
    WHERE t2.date <= t1.date AND t2.dividends <> 0
        AND t2.ticker = t1.ticker
    ORDER BY date DESC 
)ca
ORDER BY t1.ticker, date 
编辑:这里有一个更高性能的解决方案,它使用CTE为范围内的每个日期以及相应的非零红利值构建一个临时表,然后将该结果连接回您的ticker和date表。我很确定它应该与SQL Server 2008兼容:

;WITH cte_not_zero_dividends AS
(
    SELECT *, ROW_NUMBER() OVER (PARTITION BY ticker ORDER BY date) seq_num
    FROM tbl
    WHERE dividends <> 0
)
, cte_all_dates_with_dividends AS 
(
    SELECT c_start.ticker, c_start.date AS date, c_start.date AS start_range, 
        ISNULL
        (
            c_end.date, 
            (SELECT MAX(DATEADD(DAY, 1, date)) FROM dbo.tbl WHERE ticker = c_start.ticker)
        ) AS end_range, 
        c_start.dividends AS nonzero_dividends
    FROM cte_not_zero_dividends c_start
    LEFT JOIN cte_not_zero_dividends c_end 
        ON c_start.seq_num = c_end.seq_num - 1 AND c_end.ticker = c_start.ticker
    UNION ALL 
    SELECT ticker,
           DATEADD(DAY, 1, date),
           start_range,
           end_range,
           nonzero_dividends 
    FROM cte_all_dates_with_dividends
    WHERE DATEADD(DAY, 1, date) < cte_all_dates_with_dividends.end_range
)
SELECT tbl.date,
       tbl.ticker,
       cte_all_dates_with_dividends.nonzero_dividends
FROM dbo.tbl
LEFT JOIN cte_all_dates_with_dividends 
    ON cte_all_dates_with_dividends.ticker = tbl.ticker 
    AND cte_all_dates_with_dividends.date = tbl.date
ORDER BY ticker, date
OPTION (MAXRECURSION 0)
编辑:由于要计算select语句中的值,因此有一种方法:

SELECT *
FROM tbl t1
CROSS APPLY (
    SELECT TOP 1 t2.dividends AS nonzero_dividends
    FROM tbl t2 
    WHERE t2.date <= t1.date AND t2.dividends <> 0
        AND t2.ticker = t1.ticker
    ORDER BY date DESC 
)ca
ORDER BY t1.ticker, date 
编辑:这里有一个更高性能的解决方案,它使用CTE为范围内的每个日期以及相应的非零红利值构建一个临时表,然后将该结果连接回您的ticker和date表。我很确定它应该与SQL Server 2008兼容:

;WITH cte_not_zero_dividends AS
(
    SELECT *, ROW_NUMBER() OVER (PARTITION BY ticker ORDER BY date) seq_num
    FROM tbl
    WHERE dividends <> 0
)
, cte_all_dates_with_dividends AS 
(
    SELECT c_start.ticker, c_start.date AS date, c_start.date AS start_range, 
        ISNULL
        (
            c_end.date, 
            (SELECT MAX(DATEADD(DAY, 1, date)) FROM dbo.tbl WHERE ticker = c_start.ticker)
        ) AS end_range, 
        c_start.dividends AS nonzero_dividends
    FROM cte_not_zero_dividends c_start
    LEFT JOIN cte_not_zero_dividends c_end 
        ON c_start.seq_num = c_end.seq_num - 1 AND c_end.ticker = c_start.ticker
    UNION ALL 
    SELECT ticker,
           DATEADD(DAY, 1, date),
           start_range,
           end_range,
           nonzero_dividends 
    FROM cte_all_dates_with_dividends
    WHERE DATEADD(DAY, 1, date) < cte_all_dates_with_dividends.end_range
)
SELECT tbl.date,
       tbl.ticker,
       cte_all_dates_with_dividends.nonzero_dividends
FROM dbo.tbl
LEFT JOIN cte_all_dates_with_dividends 
    ON cte_all_dates_with_dividends.ticker = tbl.ticker 
    AND cte_all_dates_with_dividends.date = tbl.date
ORDER BY ticker, date
OPTION (MAXRECURSION 0)

在SQL Server 2012+或任何其他受支持的版本中,您将执行以下操作:

select t.*,
       max(dividends) over (partition by ticker, max_date) as imputed_dividends
from (select t.*,
             max(case when dividends <> 0 then date end) over (partition by ticker order by date) as max_date
      from t
     ) t;

实际上,后一种方法可以修改,以处理日期也有间隔的数据。这只需要CTE为行分配序列号。

在SQL Server 2012+或任何其他受支持的版本中,您可以执行以下操作:

select t.*,
       max(dividends) over (partition by ticker, max_date) as imputed_dividends
from (select t.*,
             max(case when dividends <> 0 then date end) over (partition by ticker order by date) as max_date
      from t
     ) t;

实际上,后一种方法可以修改,以处理日期也有间隔的数据。这只需要一个CTE为行分配一个序列号。

Hi。非常感谢您及时发送您的查询。如何仅使用select命令执行此操作?我不想更新表。我只想计算这个列,并将它用于不同的计算。查询运行得很好,但要完全运行它需要很多时间。你有没有其他方法来缩短执行时间?嗨。非常感谢您及时发送您的查询。如何仅使用select命令执行此操作?我不想更新表。我只想计算这个列,并将它用于不同的计算。查询运行得很好,但要完全运行它需要很多时间。您是否有其他方法来减少执行时间?为什么要使用不受支持的SQL Server版本?为什么要使用不受支持的SQL Server版本?