Postgresql

在 PostgreSQL 中,是否有類型安全的 first() 聚合函式?

  • November 28, 2021

我正在尋找一個**first()**聚合函式。

在這裡,我發現了一些幾乎可以工作的東西:

CREATE OR REPLACE FUNCTION public.first_agg (anyelement, anyelement)
RETURNS anyelement LANGUAGE sql IMMUTABLE STRICT AS $$
   SELECT $1;
$$;

-- And then wrap an aggregate around it
CREATE AGGREGATE public.first (
   sfunc    = public.first_agg,
   basetype = anyelement,
   stype    = anyelement
);

問題是當一varchar(n)列通過first()函式時,它被轉換為簡單的varchar(沒有大小修飾符)。嘗試在函式中返回查詢 as RETURNS SETOF anyelement,我收到以下錯誤:

ERROR: structure of query does not match function result type Estado de
SQL:42804
Detalhe:Returned type character varying does not match expected type character varying(40) in column 2.
Contexto:PL/pgSQL function vsr_table_at_time(anyelement,timestamp without time zone) line 31 at RETURN QUERY

在同一個 wiki 頁面中,有一個指向該函式的C 版本的連結,該函式將替換上述內容。我不知道如何安裝它,但我想知道這個版本是否可以解決我的問題。

同時,有沒有辦法可以更改上述函式,使其返回與輸入列完全相同的類型?

DISTINCT ON()

順便說一句,這正是DISTINCT ON()(不要與 混淆DISTINCT

SELECT DISTINCT ON ( expression [, ...] ) 只保留給定表達式計算結果為 equal 的每組行的第一行DISTINCT ON表達式使用與 for 相同的規則進行解釋(ORDER BY見上文)。ORDER BY請注意,除非用於確保所需的行首先出現,否則每組的“第一行”是不可預測的。例如

所以如果你要寫,

SELECT myFirstAgg(z)
FROM foo
GROUP BY x,y;

這是有效的

SELECT DISTINCT ON(x,y) z
FROM foo;
-- ORDER BY z;

因為它需要第一個z。有兩個重要的區別,

  1. 您還可以選擇其他列,而無需進一步聚合。
SELECT DISTINCT ON(x,y) z, k, r, t, v
FROM foo;
-- ORDER BY z, k, r, t, v;
  1. 因為沒有GROUP BY不能使用(真正的)聚合。
CREATE TABLE foo AS
SELECT * FROM ( VALUES
 (1,2,3),
 (1,2,4),
 (1,2,5)
) AS t(x,y,z);

SELECT DISTINCT ON (x,y) z, sum(z)
FROM foo;

-- fails, as you should expect.
SELECT DISTINCT ON (x,y) z, sum(z)
FROM foo;

-- would not otherwise fail.
SELECT myFirstAgg(z), sum(z)
FROM foo
GROUP BY x,y;

不要忘記ORDER BY

另外,雖然我沒有加粗,但我現在將

請注意,除非使用 ORDER BY 確保所需的行首先出現,否則每組的“第一行”是不可預測的。例如

始終使用ORDER BYwithDISTINCT ON

使用有序集聚合函式

first_value我想很多人都在尋找Ordered-Set Aggregate Functions。只是想把它扔出去。如果函式存在,它看起來像這樣:

SELECT a, b, first_value() WITHIN GROUP (ORDER BY z)    
FROM foo
GROUP BY a,b;

但是,唉,你可以做到這一點。

SELECT a, b, percentile_disc(0) WITHIN GROUP (ORDER BY z)   
FROM foo
GROUP BY a,b;

引用自:https://dba.stackexchange.com/questions/63661