在SO上已广泛讨论了寻找第一个非空值的问题,但是由于某些原因,所有的解决方案都是有问题的,可能是由于我对PostgreSQL的经验不足。表格中的结构如下:
group submitted num1 num2 num3 str1 str2 str3 ...
32 14:04:21 4.5.2020. 2 1 Null Null Null Null
32 13:01:23 4.5.2020. Null 1 0 abc def Null
37 15:01:44 3.2.2020. 2 Null 0 Null Null aar
37 03:04:21 2.1.2020. Null 1 0 abc def Null
37 23:04:00 1.1.2020. 2 Null 0 trt def abg
...
上面示例的预期结果是:
group num1 num2 num3 str1 str2 str3 ...
32 2 1 0 abc def Null
37 2 1 0 abc def aar
...
有40多个列,性能很重要。我需要每组一行包含最新的非空值,或者在上面(排序的)数据集中的第一个非空。到目前为止,我尝试过的是:
1)按提交的,分组的组进行排序,然后找不到用于查找第一个非空值的聚合函数。有没有办法以某种方式创建自定义聚集功能?
2)使用具有窗口功能的解决方案:
...
first_value(education) OVER (PARTITION BY CASE ORDER BY submitted WHEN education IS NOT NULL THEN submitted END) as education,
...
非常慢(比使用MAX的groupby慢数百倍),我觉得因为所有表都具有相同的分区,所以不应为每一列重复此操作。有没有一种方法可以对整个表进行分区,然后查找每列的第一个值?
3)一些解决方案提到了ROWNUM。这个问题(以及大多数解决方案)的问题在于,在进行第一次排序和分区之后,无需遍历该列中的所有值。
我希望的解决方案是熊猫first的类似物。
答案 0 :(得分:3)
有一个技巧,就是使用array_agg()
并删除null。那应该是:
select groupid,
(array_remove(array_agg(num1 order by submitted desc), null))[1] as num1,
(array_remove(array_agg(num2 order by submitted desc), null))[1] as num2,
. . .
from t
group by groupid;
Here是db <>小提琴。