Non ho alcun background PostgreSQL ma vediamo se funziona:
Vorrei iniziare semplificando, scrivendo una query che prima restituisce il punteggio totale per giocatore:
SELECT player_id, SUM(score) score
FROM (
SELECT first_player as player_id, first_score as score
FROM matches
UNION ALL
SELECT second_player, second_score
FROM matches
)
GROUP BY player_id
Ora, unisciti a quel set di dati ai giocatori per trovare i gruppi:
SELECT w.player_id, p.group_id, w.score
FROM
(
SELECT player_id, SUM(score) score
FROM (
SELECT first_player as player_id, first_score as score
FROM matches
UNION ALL
SELECT second_player, second_score
FROM matches
)
GROUP BY player_id
) as w
inner join players p
on p.player_id = w.player_id
Ora abbiamo tutti i giocatori, il loro punteggio totale e il loro gruppo. Vogliamo identificare il vincitore per gruppo? Possiamo utilizzare la classifica funzioni per farlo:
SELECT
w.player_id,
p.group_id,
w.score,
RANK() OVER (PARTITION BY p.group_id ORDER BY score DESC) as group_placement
FROM
(
SELECT player_id, SUM(score) score
FROM (
SELECT first_player as player_id, first_score as score
FROM matches
UNION ALL
SELECT second_player, second_score
FROM matches
)
GROUP BY player_id
) as w
inner join players p
on p.player_id = w.player_id
Ora scegliamo solo i primi in ogni gruppo (rank =1) usando WHERE
SELECT
player_id,
group_id
FROM
(
SELECT
w.player_id,
p.group_id,
w.score,
RANK() OVER (PARTITION BY p.group_id ORDER BY score DESC) as group_placement
FROM
(
SELECT player_id, SUM(score) score
FROM (
SELECT first_player as player_id, first_score as score
FROM matches
UNION ALL
SELECT second_player, second_score
FROM matches
)
GROUP BY player_id
) as w
inner join players p
on p.player_id = w.player_id
) as gp
WHERE group_placement = 1
Sembra complicato? sì, ma puoi vedere che il risultato finale viene fornito a poco a poco. Ogni passaggio di questo è una "sottotabella" e puoi eseguire e osservare i dati in ogni punto.