PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Funzione della finestra di Postgres e raggruppamento per eccezione

Tu sei non , infatti, utilizzando funzioni aggregate. Stai utilizzando funzioni finestra . Ecco perché PostgreSQL richiede sp.payout e s.buyin da inserire nel GROUP BY clausola.

Aggiungendo un OVER clausola, la funzione aggregata sum() viene trasformato in una funzione finestra, che aggrega i valori per partizione mentre mantiene tutte le righe.

Puoi combinare le funzioni della finestra e aggregare le funzioni . Le aggregazioni vengono applicate per prime. Non ho capito dalla tua descrizione come vuoi gestire più pagamenti/acquisti per evento. A titolo di ipotesi, ne calcolo una somma per evento. Ora Posso rimuovere sp.payout e s.buyin dal GROUP BY clausola e ottieni una riga per 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;

In questa espressione:sum(sum(sp.payout)) OVER w , il sum() esterno è una funzione della finestra, il sum() interno è una funzione aggregata.

Supponendo p.player_id e e.event_id sono PRIMARY KEY nelle rispettive tabelle.

Ho aggiunto e.event_id al ORDER BY della WINDOW clausola per arrivare a un ordinamento deterministico. (Potrebbero esserci più eventi nella stessa data.) Includeva anche event_id nel risultato per distinguere più eventi al giorno.

Mentre la query si limita a un singolo giocatore (WHERE p.player_id = 17 ), non è necessario aggiungere p.name o p.player_id a GROUP BY e ORDER BY . Se uno dei join moltiplichi le righe indebitamente, la somma risultante sarebbe errata (moltiplicata in parte o completamente). Raggruppamento per p.name non è stato possibile riparare la query in quel momento.

Ho anche rimosso e.date dal GROUP BY clausola. La chiave primaria e.event_id copre tutte le colonne della riga di input da PostgreSQL 9.1.

Se cambi la query per restituire più giocatori contemporaneamente, adatta:

...
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 meno che p.name è definito unico (?), raggruppa e ordina per player_id inoltre per ottenere risultati corretti in un ordinamento deterministico.

Ho mantenuto solo e.date e p.name in GROUP BY avere un ordinamento identico in tutte le clausole, sperando in un vantaggio in termini di prestazioni. Altrimenti, puoi rimuovere le colonne lì. (Simile solo per e.date nella prima query.)