我想在Postgres中执行填充操作。
DDL:
create table brands (
id int,
category varchar(20),
brand_name varchar(20)
);
insert into brands values
(1,'chocolates','5-star')
,(2,null,'dairy milk')
,(3,null,'perk')
,(4,null,'eclair')
,(5,'Biscuits','britannia')
,(6,null,'good day')
,(7,null,'boost')
,(8,'shampoo','h&s')
,(9,null,'dove')
;
预期输出是:
类别 | 品牌名称 |
---|---|
巧克力 | 5 星 |
巧克力 | 牛奶 |
巧克力 | 福利 |
巧克力 | 泡芙 |
饼干 | 不列颠尼亚 |
饼干 | 美好的一天 |
饼干 | 提升 |
洗发水 | h&s |
洗发水 | 鸽子 |
我尝试使用以下脚本,但它似乎不起作用。
select id,
first_value(category)
over(order by case when category is not null then id end desc nulls last) as category,
brand_name
from brands
有人可以建议修复吗?
在 MS SQL 中,以下代码片段似乎工作正常:
select id,
first_value (category) IGNORE NULLS
over(order by id desc
rows between current row and unbounded following) as category,
brand_name
FROM brands
ORDER BY id
with cte as (
select id,
category,
count(category) over (order by id) as category_id,
brand_name
from brands)
select id,
first_value(category) over (partition by category_id order by id) as category,
brand_name
from cte;
更新:每个请求添加了没有 CTE 的查询:
select id,
(array_agg(category) over (order by id))[max(case when category is null then 0 else id end) over (order by id)] as category,
brand_name
from brands;
我认为使用
CTE
没有什么问题(参见JHH的答案),我会更喜欢。
Postgres DB 不提供 SQLServer DB 的
IGNORE NULLS
概念,所以我想您应该停止认为您会像 MS SQL 中那样获得几乎相同的 Postgres DB 查询。
无论如何,如果您不想使用 CTE 或复杂的子查询,您可以定义自己的函数和聚合并运行它。
函数创建:
-- CREATE your function
CREATE FUNCTION yourFunction(STATE anyelement, VALUE anyelement)
RETURNS anyelement
IMMUTABLE PARALLEL safe
AS
$$
SELECT COALESCE(VALUE, STATE); -- Replace NULL values here
$$ LANGUAGE SQL;
使用函数创建聚合:
-- CREATE your aggregate
CREATE AGGREGATE yourAggregate(ANYELEMENT) (
sfunc = yourFunction, -- Call your function here
stype = ANYELEMENT
);
您使用此聚合的查询:
SELECT id,
yourAggregate(category) -- Call your aggregate here
OVER (ORDER BY id, category),
brand_name
FROM brands
ORDER BY id;
当然,您应该重命名函数和聚合,并使用更有意义的名称。
这将产生与 CTE 版本相同的结果。
尝试一下:db<>小提琴
如果您热衷于定义和使用自己的函数并且您会经常使用它,那么您可以这样做。
不然的话,用CTE就可以了。没有理由不使用 CTE。
请始终注意,在使用自己的函数时,您面临性能不佳的风险,因此您应该检查此查询是否太慢。
恐怕这在 Postgres 中还没有实现(至少在 Postgres 15 之前)。 关于窗口函数的手册:
SQL 标准定义了因此,您必须使用 CTE 或子查询(如 JHH 建议的)的解决方法,或者滚动您自己的窗口函数(这会相对较慢)。
RESPECT NULLS
或IGNORE NULLS
选项 对于lead
、lag
、first_value
、last_value
和nth_value
。这 未在 PostgreSQL 中实现:行为始终与 标准的默认值,即RESPECT NULLS
。
参见(dba.SE 上类似问题的回答):
select *, max(category) over (partition by r)
from(
select *,sum(case when category is not null then 1 end) over (order by rn) r
from
(select *,row_number() over() as rn from brands) l
)p