Nie mam żadnego tła PostgreSQL, ale zobaczmy, czy to działa:
Zacząłbym to od uproszczenia, pisząc zapytanie, które najpierw zwraca całkowity wynik gracza:
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
Teraz dołącz ten zbiór danych do graczy, aby znaleźć grupy:
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
Teraz mamy wszystkich graczy, ich łączny wynik i ich grupę. Chcemy zidentyfikować zwycięzcę według grupy? Możemy użyć rankingu funkcje do tego:
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
Teraz po prostu wybieramy najlepsze w każdej grupie (ranga =1) za pomocą 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
Wygląda na skomplikowaną? tak, ale widać, że końcowy wynik jest dostarczany po trochu. Każdy krok to „podtablica” i możesz uruchamiać i obserwować dane w każdym punkcie.