Det er ikke kønt, men jeg fandt en løsning:
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;
I den rekursive del af forespørgslen, i stedet for at kalde GROUP BY
og beregning af avg(r.rank)
, Jeg bruger en vinduesfunktion, der er partitioneret på de samme kolonner. Dette har samme effekt ved at beregne den gennemsnitlige rangering.
En ulempe er, at denne beregning sker flere gange end nødvendigt. Hvis vi kunne GROUP BY
derefter avg(r.rank)
, det ville være mere effektivt end avg(r.rank)
derefter GROUP BY
.
Da der nu er dubletter i resultatet af den indlejrede forespørgsel, bruger jeg DISTINCT
for at filtrere disse fra, og derefter beregner den ydre forespørgsel en RANK()
af alle atleter i hver category_id
baseret på disse gennemsnit.
Jeg vil stadig gerne høre, om nogen kender til en bedre måde at gøre dette på. Tak