Я не вижу хороших вариантов для вас, но вот два подхода, которые вы могли бы рассмотреть.
ВАРИАНТ 1 - Рекурсивный CTE
В этом подходе вы используете рекурсивныйзапрос, где каждое дочернее значение равно себе или, если оно равно нулю, значение его родителя.Примерно так:
WITH
ordered AS (
SELECT yt.*
row_number() over ( partition by yt.personid order by yt.yearmonth ) rn
FROM YOUR_TABLE yt),
downfilled ( personid, yearmonth, var1, var2, ..., var300, rn) as (
SELECT o.*
FROM ordered o
WHERE o.rn = 1
UNION ALL
SELECT c.personid, c.yearmonth,
nvl(c.var1, p.var1) var1,
nvl(c.var2, p.var2) var2,
...
nvl(c.var300, p.var300) var300
FROM downfilled p INNER JOIN ordered c ON c.personid = p.personid AND c.rn = p.rn + 1 )
SELECT * FROM downfilled
ORDER BY personid, yearmonth;
Это заменяет каждое выражение следующим образом:
last_value(var2) OVER (PARTITION BY Person_ID ORDER BY Date ASC
RANGE BETWEEN UNBOUNDED PRECEDING) as Var2
на выражение, подобное этому:
NVL(c.var2, p.var2)
Один недостаток, однако, заключается в том, чтоэто заставляет вас повторить список из 300 столбцов дважды (один раз для выражений 300 NVL()
и один раз, чтобы указать выходные столбцы рекурсивного CTE (downfilled
).
ВАРИАНТ 2 - снова UNPIVOT и PIVOT
В этом подходе вы UNPIVOT
ваших VARxx
столбцов в строки, так что вам нужно всего лишь один раз написать выражение last_value()...
.
SELECT personid,
yearmonth,
var_column,
last_value(var_value ignore nulls)
over ( partition by personid, var_column order by yearmonth ) var_value
FROM YOUR_TABLE
UNPIVOT INCLUDE NULLS ( var_value FOR var_column IN ("VAR1","VAR2","VAR3") ) )
SELECT * FROM unp
PIVOT ( max(var_value) FOR var_column IN ('VAR1' AS VAR1, 'VAR2' AS VAR, 'VAR3' AS VAR3 ) )
Здесь вам все еще нужноперечислить каждый столбец дважды. Кроме того, я не уверен, какой будет производительность, если у вас большой набор данных.