No tengo antecedentes en PostgreSQL, pero veamos si esto funciona:
Comenzaría esto simplificándolo, escribiendo una consulta que primero devuelva el puntaje total por jugador:
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
Ahora, une ese conjunto de datos a los jugadores para encontrar los grupos:
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
Ahora tenemos todos los jugadores, su puntuación total y su grupo. ¿Queremos identificar al ganador por grupo? Podemos usar ranking funciones para hacer esto:
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
Ahora seleccionamos los primeros en cada grupo (rango =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
¿Parece complicado? sí, pero puede ver que el resultado final se proporciona poco a poco. Cada paso de esto es una 'subtabla' y puede ejecutar y observar los datos en cada punto.