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.)