Использование функции last_value для каждого столбца |Свернуть все нули в таблице - PullRequest
0 голосов
/ 24 апреля 2019

У меня есть таблица отдельных уровней, упорядоченная по Person_ID и Date по возрастанию.На уровне Person_ID есть повторяющиеся записи.То, что я хотел бы сделать, это «пустить» нулевые значения в каждом столбце - у меня сложилось впечатление, что функция last_value (| ignore nulls) будет отлично работать для каждого столбца.

Основная проблема заключается в том, что таблицасотни столбцов в ширину, и довольно динамичный (создание функции для экспериментов ML).Должен быть лучший способ, чем выписывать оператор last_value для каждой переменной, что-то вроде этого:

SELECT last_value(var1) OVER (PARTITION BY Person_ID ORDER BY Date ASC
             RANGE BETWEEN UNBOUNDED PRECEDING) as Var1,
       last_value(var2) OVER (PARTITION BY Person_ID ORDER BY Date ASC
             RANGE BETWEEN UNBOUNDED PRECEDING) as Var2,
       ...
       last_value(var300) OVER (PARTITION BY Person_ID ORDER BY Date ASC
             RANGE BETWEEN UNBOUNDED PRECEDING) as Var3
FROM TABLE

В суммировании у меня есть следующая таблица:

+----------+-----------+------+------+---+------------+
| PersonID | YearMonth | Var1 | Var2 | … |   Var300   |
+----------+-----------+------+------+---+------------+
|        1 |    200901 | 2    | null |   | null       |
|        1 |    200902 | null | 1    |   | Category 1 |
|        1 |    201010 | null | 1    |   | null       |
+----------+-----------+------+------+---+------------+

ижелаю следующую таблицу:

+----------+-----------+------+------+---+------------+
| PersonID | YearMonth | Var1 | Var2 | … |   Var300   |
+----------+-----------+------+------+---+------------+
|        1 |    200901 |    2 | null |   | null       |
|        1 |    200902 |    2 | 1    |   | Category 1 |
|        1 |    201010 |    2 | 1    |   | Category 1 |
+----------+-----------+------+------+---+------------+

1 Ответ

1 голос
/ 24 апреля 2019

Я не вижу хороших вариантов для вас, но вот два подхода, которые вы могли бы рассмотреть.

ВАРИАНТ 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 ) )

Здесь вам все еще нужноперечислить каждый столбец дважды. Кроме того, я не уверен, какой будет производительность, если у вас большой набор данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...