用SQL Server中以前的非零值填充零值
我试图用之前给定的股息数据填充所有行的零值。如何使用先前给定的红利填充零值,以及如何对MS SQL server中的所有给定行进行填充 如何使用SELECT命令而不使用UPDATE命令执行此操作用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 |
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版本?