[英]How to use first_value window function to get last non null value in Postgresql
我想在 PgSQL 中執行填充活動
動態鏈接庫:
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');
預計 output 是:
類別 | 品牌 |
---|---|
巧克力 | 5星級 |
巧克力 | 牛奶 |
巧克力 | 津貼 |
巧克力 | 泡芙 |
餅干 | 大不列顛 |
餅干 | 再會 |
餅干 | 促進 |
洗發水 | 健康與安全 |
洗發水 | 鴿子 |
我嘗試使用以下腳本,但它似乎不起作用。
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
概念,所以我想你應該停止認為你會得到一個幾乎相同的 Postgres DB 查詢,就像在 MS SQL 中一樣。
無論如何,如果您不想使用 CTE 或復雜的子查詢,您可以定義自己的 function 和聚合並運行它。
Function 創作:
-- 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;
使用 function 聚合創建:
-- 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;
當然,您應該將 function 和聚合都重命名並使用更有意義的名稱。
這將產生與 CTE 版本相同的結果。
嘗試: db<>fiddle
如果您熱衷於定義和使用自己的功能並且您會經常使用它,那么您可以這樣做。
否則,只需使用 CTE,就可以了。 沒有理由不使用 CTE。
請始終注意,在使用自己的函數時,您面臨性能不佳的風險,因此您應該檢查此查詢是否太慢。
恐怕這在 Postgres 中沒有實現(至少在 Postgres 15 之前)。 關於 window 函數的手冊:
SQL 標准為
lead
、lag
、first_value
、last_value
和nth_value
定義了RESPECT NULLS
或IGNORE NULLS
選項。 這在 PostgreSQL 中沒有實現:行為始終與標准的默認值相同,即RESPECT NULLS
。
因此,您必須使用 CTE 的變通方法或像 JHH 建議的子查詢,或者滾動您自己的 window function(這將相對較慢)。
請參閱(對 dba.SE 上類似問題的回答):
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.