UPDATE t1
SET dividends = (
SELECT TOP 1 dividends
FROM tbl t2
WHERE t2.date < t1.date AND t2.dividends <> 0
AND t2.ticker = t1.ticker
ORDER BY date DESC)
FROM tbl t1
WHERE dividends = 0
Here's a fiddle.
Edit: Since you want to compute the value in a select statement, here's an approach:
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
Here's another fiddle.
Edit: Here's a more performant solution that uses CTEs to build a temp table of every date in the range along with the corresponding nonzero dividend value, and then joins that result back to your table on ticker and date. I'm pretty sure it should be compatible with 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)
Hopefully the last fiddle.