Usted no , de hecho, usando funciones agregadas. Está utilizando funciones de ventana . Es por eso que PostgreSQL exige sp.payout
y s.buyin
para ser incluido en el GROUP BY
cláusula.
Agregando un OVER
cláusula, la función agregada sum()
se convierte en una función de ventana, que agrega valores por partición mientras mantiene todas las filas.
Puede combinar funciones de ventana y funciones agregadas . Las agregaciones se aplican primero. No entendí a partir de su descripción cómo desea manejar múltiples pagos/compras por evento. Como suposición, calculo una suma de ellos por evento. Ahora Puedo eliminar sp.payout
y s.buyin
del GROUP BY
cláusula y obtener una fila por player
y 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;
En esta expresión:sum(sum(sp.payout)) OVER w
, el exterior sum()
es una función de ventana, el sum()
interno es una función agregada.
Asumiendo p.player_id
y e.event_id
son PRIMARY KEY
en sus respectivas tablas.
Agregué e.event_id
al ORDER BY
de la WINDOW
cláusula para llegar a un orden de clasificación determinista. (Puede haber varios eventos en la misma fecha). También se incluye event_id
en el resultado para distinguir múltiples eventos por día.
Mientras que la consulta se restringe a un único jugador (WHERE p.player_id = 17
), no necesitamos agregar p.name
o p.player_id
a GROUP BY
y ORDER BY
. Si una de las combinaciones multiplicara filas indebidamente, la suma resultante sería incorrecta (multiplicada parcial o totalmente). Agrupación por p.name
entonces no se pudo reparar la consulta.
También eliminé e.date
del GROUP BY
cláusula. La clave principal e.event_id
cubre todas las columnas de la fila de entrada desde PostgreSQL 9.1.
Si cambia la consulta para devolver varios jugadores a la vez, 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
se define único (?), grupo y orden por player_id
adicionalmente para obtener resultados correctos en un orden de clasificación determinista.
Solo conservé e.date
y p.name
en GROUP BY
tener un orden de clasificación idéntico en todas las cláusulas, esperando un beneficio de rendimiento. De lo contrario, puede eliminar las columnas allí. (Similar para solo e.date
en la primera consulta.)