sql >> Databáze >  >> RDS >> PostgreSQL

Funkce okna Postgres a seskupení podle výjimky

nejste ve skutečnosti pomocí agregačních funkcí. Používáte funkce oken . To je důvod, proč PostgreSQL požaduje sp.payout a s.buyin být zahrnut do GROUP BY doložka.

Připojením OVER klauzule, agregační funkce sum() se změní na funkci okna, která agreguje hodnoty na oddíl a přitom zachovává všechny řádky.

Můžete kombinovat funkce okna a agregační funkce . Nejprve se použijí agregace. Z vašeho popisu jsem nepochopil, jak chcete zacházet s více výplatami / buyiny za událost. Odhadem vypočítám jejich součet na událost. Nyní Mohu odstranit sp.payout a s.buyin z GROUP BY klauzule a získáte jeden řádek na player a 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;

V tomto výrazu:sum(sum(sp.payout)) OVER w , vnější sum() je funkce okna, vnitřní sum() je agregační funkce.

Za předpokladu p.player_id a e.event_id jsou PRIMARY KEY v příslušných tabulkách.

Přidal jsem e.event_id do ORDER BY z WINDOW klauzule k dosažení deterministického pořadí řazení. (Ve stejném datu může být více událostí.) Zahrnuje také event_id ve výsledku rozlišit více událostí za den.

Zatímco dotaz se omezuje na jeden hráč (WHERE p.player_id = 17 ), nemusíme přidávat p.name nebo p.player_id na GROUP BY a ORDER BY . Pokud by jedno ze spojení nepatřičně násobilo řádky, výsledný součet by byl nesprávný (částečně nebo úplně vynásobený). Seskupení podle p.name nemohl poté dotaz opravit.

Také jsem odstranil e.date z GROUP BY doložka. Primární klíč e.event_id pokrývá všechny sloupce vstupního řádku od PostgreSQL 9.1.

Pokud změníte dotaz tak, aby vracel více hráčů najednou, přizpůsobte:

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

Pokud není p.name je definována jedinečná (?), skupina a pořadí pomocí player_id navíc získat správné výsledky v deterministickém pořadí řazení.

Ponechal jsem pouze e.date a p.name v GROUP BY mít identické pořadí řazení ve všech klauzulích v naději na výkonnost. Jinak tam můžete sloupce odstranit. (Podobné pouze pro e.date v prvním dotazu.)




  1. SQL Server dotaz k nalezení všech oprávnění/přístupu pro všechny uživatele v databázi

  2. Použití IS NULL nebo IS NOT NULL v podmínkách spojení - teoretická otázka

  3. Co je DATALENGTH() v SQL Server?

  4. Jak vložit obrázek do knihovny persistence místnosti?