Para obter o resultado sem subconsulta , você deve recorrer a truques avançados de função de janela:
SELECT sum(count(*)) OVER () AS tickets_count
, sum(min(a.revenue)) OVER () AS atendees_revenue
FROM tickets t
JOIN attendees a ON a.id = t.attendee_id
GROUP BY t.attendee_id
LIMIT 1;
sqlfiddle
Como funciona?
A chave para entender isso é a sequência de eventos na consulta:
funções agregadas -> funções de janela -> DISTINCT -> LIMIT
Mais detalhes:
- Melhor maneira de obter a contagem de resultados antes da aplicação de LIMIT
Passo a passo:
-
IGROUP BY t.attendee_id
- o que você normalmente faria em uma subconsulta.
-
Então eu somei as contagens para obter a contagem total de ingressos. Não muito eficiente, mas forçado por sua exigência. A função agregadacount(*)
é envolvido na função de janelasum( ... ) OVER ()
para chegar à expressão não tão comum:sum(count(*)) OVER ()
.
E some a receita mínima por participante para obter a soma sem duplicatas.
Você também pode usarmax()
ouavg()
em vez demin()
com o mesmo efeito querevenue
é garantido para ser o mesmo para todas as linhas por participante.
Isso poderia ser mais simples seDISTINCT
era permitido em funções de janela, mas o PostgreSQL (ainda) não implementou esse recurso. Por documentação:
Funções de janela agregadas, ao contrário das funções agregadas normais, não permitemDISTINCT
ouORDER BY
para ser usado dentro da lista de argumentos da função.
-
O passo final é obter uma única linha. Isso pode ser feito comDISTINCT
(padrão SQL), pois todas as linhas são iguais.LIMIT 1
será mais rápido, no entanto. Ou o formulário padrão SQLFETCH FIRST 1 ROWS ONLY
.