Seguindo combinando array_agg e unnest , dados estes dados:
key | a | b | c
------------------
1 | 0 | 1 | {1,2}
1 | 1 | 2 | {3}
1 | -1 | 3 | {2}
1 | 2 | 4 | {}
Executando esta consulta:
SELECT
d.key,
min(d.a) AS a,
sum(d.b) AS b,
array_agg(DISTINCT x.c) AS c
FROM data AS d
CROSS JOIN LATERAL unnest(d.c) AS x(c)
GROUP BY d.key
Dá o resultado inesperado:
key | a | b | c
------------------
1 | -1 | 7 | {1,2,3}
O que está acontecendo aqui, e como obter a soma correta?
Desempenho da resposta
Em meus dados reais (16.642 linhas, 1.942 chaves, 6 agregados), recebo essas estimativas de custo para cada solução sugerida.
- a_horse_with_no_name opção 1:
1761.12..49370.52
- a_horse_with_no_name opção 2:
0.57..89214.72
- Erwin Brandstetter :
1761.12..49370.61
O desaninhamento gera 2 linhas para (chave = 1, a = 0, b = 1) e a junção cruzada remove a linha com a matriz vazia.
Portanto, seu grupo opera no seguinte conjunto:
Uma solução é combinar duas consultas agrupadas por consultas, cada uma agrupando em um nível diferente:
Outra abordagem é incluir apenas a "primeira linha" para cada grupo "não aninhado" nos agregados:
with ordinality
retorna a posição do elemento não aninhado na matriz original. Para a linha com a matriz vazia, isso será nulo.Um problema com sua consulta é que
CROSS JOIN
elimina linhas ondeunnest()
não produz linhas (acontece para o array vazio{}
).Você pode corrigir isso com
LEFT JOIN .. ON true
, mas o outro problema é que as linhas são multiplicadas ondeunnest()
retorna várias linhas (acontece para{1,2}
).É assim que você obtém
7
a soma:1 + 1 + 2 + 3
.Unir duas subconsultas separadas pode ser mais simples/rápido:
A junção simples funciona porque ambas as subconsultas foram agrupadas pela mesma coluna - e contanto que
key
sejaNOT NULL
.db<>fique aqui
Relacionado: