PostgreSQL last_value 忽略空值
PostgreSQL last_value ignore nulls
我知道有人问过这个问题,但为什么下面的解决方案不起作用?我想用 idx
.
排序的最后一个非空值填充 value
我看到的:
idx | coalesce
-----+----------
1 | 2
2 | 4
3 |
4 |
5 | 10
(5 rows)
我想要的:
idx | coalesce
-----+----------
1 | 2
2 | 4
3 | 4
4 | 4
5 | 10
(5 rows)
代码:
with base as (
select 1 as idx
, 2 as value
union
select 2 as idx
, 4 as value
union
select 3 as idx
, null as value
union
select 4 as idx
, null as value
union
select 5 as idx
, 10 as value
)
select idx
, coalesce(value
, last_value(value) over (order by case when value is null then -1
else idx
end))
from base
order by idx
要了解您的解决方案为何不起作用,如果您按照 window 框架中的顺序进行排序,只需查看输出:
with base as (
select 1 as idx
, 2 as value
union
select 2 as idx
, 4 as value
union
select 3 as idx
, null as value
union
select 4 as idx
, null as value
union
select 5 as idx
, 10 as value
)
select idx, value from base
order by case when value is null then -1
else idx
end;
idx | value
-----+-------
3 |
4 |
1 | 2
2 | 4
5 | 10
last_value() window 函数将选择当前帧中的最后一个值。在不更改任何框架默认值的情况下,这将是当前行。
你要的是lag(ignore nulls)
。这是一种使用两个 window 函数来做你想做的事情的方法。第一个定义 NULL
值的分组,第二个分配值:
select idx, value, coalesce(value, max(value) over (partition by grp))
from (select b.*, count(value) over (order by idx) as grp
from base b
) b
order by idx;
您也可以使用数组在没有子查询的情况下执行此操作。基本上,取最后一个不计算 NULL
s:
的元素
select idx, value,
(array_remove(array_agg(value) over (order by idx), null))[count(value) over (order by idx)]
from base b
order by idx;
Here 是一个 db<>fiddle.
嗯,这里的 last_value 对我来说没有意义,除非你能指出给我。查看示例,您需要最后一个非值,您可以通过以下方式获取它:
我正在用空值和先前的非空值组成一个组,以便我可以获得第一个非值。
with base as (
select 1 as idx , 2 as value union
select 2 as idx, -14 as value union
select 3 as idx , null as value union
select 4 as idx , null as value union
select 5 as idx , 1 as value
)
Select idx,value,
first_value(value) Over(partition by rn) as new_val
from(
select idx,value
,sum(case when value is not null then 1 end) over (order by idx) as rn
from base
) t
这是代码
我知道有人问过这个问题,但为什么下面的解决方案不起作用?我想用 idx
.
value
我看到的:
idx | coalesce
-----+----------
1 | 2
2 | 4
3 |
4 |
5 | 10
(5 rows)
我想要的:
idx | coalesce
-----+----------
1 | 2
2 | 4
3 | 4
4 | 4
5 | 10
(5 rows)
代码:
with base as (
select 1 as idx
, 2 as value
union
select 2 as idx
, 4 as value
union
select 3 as idx
, null as value
union
select 4 as idx
, null as value
union
select 5 as idx
, 10 as value
)
select idx
, coalesce(value
, last_value(value) over (order by case when value is null then -1
else idx
end))
from base
order by idx
要了解您的解决方案为何不起作用,如果您按照 window 框架中的顺序进行排序,只需查看输出:
with base as (
select 1 as idx
, 2 as value
union
select 2 as idx
, 4 as value
union
select 3 as idx
, null as value
union
select 4 as idx
, null as value
union
select 5 as idx
, 10 as value
)
select idx, value from base
order by case when value is null then -1
else idx
end;
idx | value
-----+-------
3 |
4 |
1 | 2
2 | 4
5 | 10
last_value() window 函数将选择当前帧中的最后一个值。在不更改任何框架默认值的情况下,这将是当前行。
你要的是lag(ignore nulls)
。这是一种使用两个 window 函数来做你想做的事情的方法。第一个定义 NULL
值的分组,第二个分配值:
select idx, value, coalesce(value, max(value) over (partition by grp))
from (select b.*, count(value) over (order by idx) as grp
from base b
) b
order by idx;
您也可以使用数组在没有子查询的情况下执行此操作。基本上,取最后一个不计算 NULL
s:
select idx, value,
(array_remove(array_agg(value) over (order by idx), null))[count(value) over (order by idx)]
from base b
order by idx;
Here 是一个 db<>fiddle.
嗯,这里的 last_value 对我来说没有意义,除非你能指出给我。查看示例,您需要最后一个非值,您可以通过以下方式获取它: 我正在用空值和先前的非空值组成一个组,以便我可以获得第一个非值。
with base as (
select 1 as idx , 2 as value union
select 2 as idx, -14 as value union
select 3 as idx , null as value union
select 4 as idx , null as value union
select 5 as idx , 1 as value
)
Select idx,value,
first_value(value) Over(partition by rn) as new_val
from(
select idx,value
,sum(case when value is not null then 1 end) over (order by idx) as rn
from base
) t
这是代码