sql >> Database >  >> RDS >> PostgreSQL

Postgres-vensterfunctie en groeperen op uitzondering

Je bent niet , in feite met behulp van geaggregeerde functies. U gebruikt vensterfuncties . Daarom eist PostgreSQL sp.payout en s.buyin op te nemen in de GROUP BY clausule.

Door een OVER . toe te voegen clausule, de aggregatiefunctie sum() wordt omgezet in een vensterfunctie, die waarden per partitie verzamelt terwijl behouden alle rijen.

U kunt vensterfuncties en aggregatiefuncties combineren . Aggregaties worden eerst toegepast. Ik begreep uit je beschrijving niet hoe je wilt omgaan met meerdere uitbetalingen/buy-ins per evenement. Als gok bereken ik een som hiervan per gebeurtenis. Nu Ik kan sp.payout verwijderen en s.buyin uit de GROUP BY clausule en krijg één rij per player en 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 deze uitdrukking:sum(sum(sp.payout)) OVER w , de buitenste sum() is een vensterfunctie, de binnenste sum() is een geaggregeerde functie.

Ervan uitgaande dat p.player_id en e.event_id zijn PRIMARY KEY in hun respectievelijke tabellen.

Ik heb e.event_id . toegevoegd naar de ORDER BY van het WINDOW clausule om tot een deterministische sorteervolgorde te komen. (Er kunnen meerdere evenementen op dezelfde datum zijn.) Ook event_id in het resultaat om meerdere gebeurtenissen per dag te onderscheiden.

Terwijl de zoekopdracht beperkt is tot een enkele speler (WHERE p.player_id = 17 ), hoeven we p.name niet toe te voegen of p.player_id naar GROUP BY en ORDER BY . Als een van de joins rijen onnodig zou vermenigvuldigen, zou de resulterende som onjuist zijn (gedeeltelijk of volledig vermenigvuldigd). Groeperen op p.name kon de query toen niet herstellen.

Ik heb ook e.date verwijderd uit de GROUP BY clausule. De primaire sleutel e.event_id omvat alle kolommen van de invoerrij sinds PostgreSQL 9.1.

Als je verandert de zoekopdracht om meerdere spelers tegelijk te retourneren, pas aan:

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

Tenzij p.name wordt gedefinieerd als uniek (?), groep en volgorde door player_id bovendien om correcte resultaten te krijgen in een deterministische sorteervolgorde.

Ik heb alleen e.date bewaard en p.name in GROUP BY identieke sorteervolgorde in alle clausules hebben, in de hoop op een prestatievoordeel. Anders kunt u de kolommen daar verwijderen. (Vergelijkbaar voor slechts e.date in de eerste zoekopdracht.)




  1. XML ontleden in SQL Server

  2. Hoe SQL Server op SUSE 12 te installeren

  3. hoe tekenreeksen samenvoegen?

  4. Verlaag de licentiekosten voor SQL Server