Het is niet mooi, maar ik heb een oplossing gevonden:
WITH RECURSIVE rankings(rankable_type, rankable_id, athlete, value, rank) AS (
SELECT 'Sport', sport_id, athlete, seconds, RANK() over(PARTITION BY sport_id ORDER BY seconds)
FROM lap_times lt
UNION ALL
SELECT 'Category', *, rank() OVER(PARTITION by category_id ORDER BY avg_rank) FROM (
SELECT DISTINCT category_id, athlete, avg(r.rank) OVER (PARTITION by category_id, athlete) AS avg_rank
FROM categories c
JOIN memberships m ON m.category_id = c.id
JOIN rankings r ON r.rankable_type = m.member_type AND r.rankable_id = m.member_id
) _
)
SELECT * FROM rankings;
In het recursieve deel van de query, in plaats van GROUP BY
. aan te roepen en het berekenen van avg(r.rank)
, Ik gebruik een vensterfunctie gepartitioneerd op dezelfde kolommen. Dit heeft hetzelfde effect als het berekenen van de gemiddelde rangorde.
Een nadeel is dat deze berekening vaker voorkomt dan nodig is. Als we konden GROUP BY
dan avg(r.rank)
, dat zou efficiënter zijn dan avg(r.rank)
dan GROUP BY
.
Aangezien er nu duplicaten zijn in het resultaat van de geneste zoekopdracht, gebruik ik DISTINCT
om deze eruit te filteren en dan berekent de buitenste query een RANK()
van alle atleten in elke category_id
gebaseerd op deze gemiddelden.
Ik hoor het graag als iemand een betere manier weet om dit te doen. Bedankt