我在Postgres中有一个表,看起来像这样:
# select * from p;
id | value
----+-------
1 | 100
2 |
3 |
4 |
5 |
6 |
7 |
8 | 200
9 |
(9 rows)
我想查询一下,使它看起来像这样:
# select * from p;
id | value | new_value
----+-------+----------
1 | 100 |
2 | | 100
3 | | 100
4 | | 100
5 | | 100
6 | | 100
7 | | 100
8 | 200 | 100
9 | | 200
(9 rows)
我已经可以在select中使用子查询来实现这一点,但是在我的真实的数据中,我有20k或更多的行,这会变得相当慢。
这可以在窗口函数中实现吗?我喜欢使用lag(),但是它似乎不支持IGNORE NULLS选项。
select id, value, lag(value, 1) over (order by id) as new_value from p;
id | value | new_value
----+-------+-----------
1 | 100 |
2 | | 100
3 | |
4 | |
5 | |
6 | |
7 | |
8 | 200 |
9 | | 200
(9 rows)
8条答案
按热度按时间nhhxz33t1#
我发现this answer for SQL Server也可以在Postgres中工作。我以前从来没有做过,我认为这个技术相当聪明。基本上,他通过使用嵌套查询内的case语句来创建用于开窗函数的定制分区,该嵌套查询当值不为空时递增总和,否则不加处理。这允许用户使用与前一个非空值相同的数字来描述每个空部分。
结果是:
wwwo4jvm2#
你可以在Postgres中创建一个自定义的聚合函数,下面是
int
类型的一个例子:然后照常查询。
iyfjxgzm3#
嗯,我不能保证这是最有效的方式,但工作:
以下索引可以改进大型数据集的子查询:
假设
value
是稀疏的(例如,有很多空值),它将运行良好。nnt7mjpx4#
另一种可能性是建立一个总和:
4ktjp1zp5#
可以使用ARRAY_AGG模拟
LAG(...)/LEAD(...) IGNORE NULLS
并访问最后一个NOT NULL值:对于输入数据:
精简版:
代码重复看起来不太好,如果有方法使用
some_array[-1]
访问最后一个元素,会容易得多。**一个
使用Lukas的建议:
xkftehaa6#
在我的情况下,我需要在非交易日维持一个运行平衡,这只是周末,偶尔在非交易假日的情况下,三天的周末
如果空闲天数非常少,可以通过CASE语句和一系列LAG窗口函数来解决此问题:
对于无界问题不实用,但对于小的差距是一个很好的解决方案。如果需要的话,只需添加更多的“WHEN LAG(,x)...”子句。我很幸运,我只需要对一列进行此操作,并且此解决方案为我的目标扫清了障碍
nwlqm0z17#
然后我们将使用聚合函数与过滤器选项。
vltsax258#
您可以将LAST_VALUE与FILTER一起使用来实现您所需要的(至少在PG 9.4中)