在每列上使用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函数下载表中的所有空值的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Snowflake Javascript 存储过程或函数遍历表中的所有列?
如何使用javascript从数据库中向动态表中添加不同的列