Estou procurando uma first()
função agregada.
Aqui encontrei algo que quase funciona:
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
);
O problema é que quando uma varchar(n)
coluna passa pela first()
função, ela é convertida em simples varchar
(sem modificador de tamanho). Tentando retornar a consulta em uma função as RETURNS SETOF anyelement
, recebo o seguinte erro:
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
Na mesma página wiki há um link para uma versão C da função que substituiria a acima. Não sei como instalá-lo, mas gostaria de saber se esta versão poderia resolver meu problema.
Enquanto isso, existe uma maneira de alterar a função acima para que ela retorne exatamente o mesmo tipo da coluna de entrada?
DISTINCT ON()
Apenas como uma nota lateral, é exatamente isso
DISTINCT ON()
que (não deve ser confundido comDISTINCT
)Então, se você fosse escrever,
É efetivamente
Em que leva o primeiro
z
. Existem duas diferenças importantes,Você também pode selecionar outras colunas sem custo de agregação adicional.
Porque não há
GROUP BY
você não pode usar agregados (reais) com ele.Não se esqueça
ORDER BY
Além disso, embora eu não tenha colocado em negrito, agora vou
Sempre use um
ORDER BY
comDISTINCT ON
Usando uma função agregada de conjunto ordenado
Imagino que muitas pessoas estejam procurando por Funções Agregadas de Conjunto
first_value
Ordenado . Só queria jogar isso lá fora. Ficaria assim, se a função existisse:Mas, infelizmente, você pode fazer isso.
Yay, eu descobri uma maneira fácil com o seu caso usando alguns recursos do PostgreSQL 9.4+
Vejamos este exemplo:
Espero que ajude no seu caso.
Não é uma resposta direta à sua pergunta, mas você deve tentar a
first_value
função de janela. Funciona assim:);
Então, se você quiser o primeiro item em cada
cat
(categoria), você consultará assim:ou:
Tenho certeza de que a pergunta não é mais real para o iniciador do tópico, mas para quem procura solução em 2021, há um truque simples - array_agg
por exemplo :
SELECT (array_agg(t.f0) FILTER (WHERE t.f0 IS NOT NULL))[1] agg FROM t GROUP BY t.f1