Você não , na verdade, usando funções agregadas. Você está usando funções de janela . É por isso que o PostgreSQL exige
sp.payout e s.buyin para ser incluído no GROUP BY cláusula. Ao anexar um
OVER cláusula, a função agregada sum() é transformado em uma função de janela, que agrega valores por partição enquanto mantendo todas as linhas. Você pode combinar funções de janela e funções agregadas . As agregações são aplicadas primeiro. Não entendi na sua descrição como você deseja lidar com vários pagamentos / buy-ins por evento. Como um palpite, calculo uma soma deles por evento. Agora Posso remover
sp.payout e s.buyin do GROUP BY cláusula e obter uma linha por player e event :SELECT p.name
, e.event_id
, e.date
, sum(sum(sp.payout)) OVER w
- sum(sum(s.buyin )) OVER w AS "Profit/Loss"
FROM player p
JOIN result r ON r.player_id = p.player_id
JOIN game g ON g.game_id = r.game_id
JOIN event e ON e.event_id = g.event_id
JOIN structure s ON s.structure_id = g.structure_id
JOIN structure_payout sp ON sp.structure_id = g.structure_id
AND sp.position = r.position
WHERE p.player_id = 17
GROUP BY e.event_id
WINDOW w AS (ORDER BY e.date, e.event_id)
ORDER BY e.date, e.event_id;
Nesta expressão:
sum(sum(sp.payout)) OVER w , a sum() externa é uma função de janela, a sum() interna é uma função agregada. Supondo
p.player_id e e.event_id são PRIMARY KEY em suas respectivas tabelas. Eu adicionei
e.event_id para o ORDER BY da WINDOW cláusula para chegar a uma ordem de classificação determinística. (Pode haver vários eventos na mesma data.) Também incluído event_id no resultado para distinguir vários eventos por dia. Enquanto a consulta se restringe a um único player (
WHERE p.player_id = 17 ), não precisamos adicionar p.name ou p.player_id para GROUP BY e ORDER BY . Se uma das junções multiplicasse as linhas indevidamente, a soma resultante seria incorreta (multiplicada parcial ou completamente). Agrupando por p.name não foi possível reparar a consulta então. Eu também removi
e.date do GROUP BY cláusula. A chave primária e.event_id cobre todas as colunas da linha de entrada desde o PostgreSQL 9.1. Se você altera a consulta para retornar vários jogadores ao mesmo tempo, adapte:
...
WHERE p.player_id < 17 -- example - multiple players
GROUP BY p.name, p.player_id, e.date, e.event_id -- e.date and p.name redundant
WINDOW w AS (ORDER BY p.name, p.player_id, e.date, e.event_id)
ORDER BY p.name, p.player_id, e.date, e.event_id;
A menos que
p.name é definido como único (?), grupo e ordem por player_id além disso, para obter resultados corretos em uma ordem de classificação determinística. Eu só mantive
e.date e p.name em GROUP BY ter ordem de classificação idêntica em todas as cláusulas, esperando um benefício de desempenho. Caso contrário, você pode remover as colunas de lá. (Semelhante para apenas e.date na primeira consulta.)