在每列上使用last_value函数下载表中的所有空值

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在每列上使用last_value函数下载表中的所有空值相关的知识,希望对你有一定的参考价值。

我有一个单独的级别表,按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 |
+----------+-----------+------+------+---+------------+
答案

我没有看到任何很好的选择,但这里有两种方法可供您研究。

OPTION 1 -- Recursive CTE

在此方法中,您使用递归查询,其中每个子值等于其自身,如果为null,则为其父值。像这样:

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)的输出列。

OPTION 2 -- UNPIVOT and PIVOT again

在这种方法中,你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 ) )

在这里,您仍需要列出每列两次。另外,如果您拥有大型数据集,我不确定性能会是什么样的。

以上是关于在每列上使用last_value函数下载表中的所有空值的主要内容,如果未能解决你的问题,请参考以下文章

替换Hive表中所有列的字符

Cublas - 列/行明智的操作

如何使用 Snowflake Javascript 存储过程或函数遍历表中的所有列?

如何使用javascript从数据库中向动态表中添加不同的列

Python:查找所有 6x6 矩阵,其中每个值在每列和每行中仅出现一次

每行每列的最小元素