Não é bonito, mas encontrei uma solução:
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;
Na parte recursiva da consulta, em vez de chamar
GROUP BY
e calculando avg(r.rank)
, eu uso uma função de janela particionada nas mesmas colunas. Isso tem o mesmo efeito de calcular a classificação média. Uma desvantagem é que esse cálculo acontece mais vezes do que o necessário. Se pudéssemos
GROUP BY
então avg(r.rank)
, isso seria mais eficiente que avg(r.rank)
então GROUP BY
. Como agora há duplicatas no resultado da consulta aninhada, estou usando
DISTINCT
para filtrá-los e, em seguida, a consulta externa calcula um RANK()
de todos os atletas em cada category_id
com base nessas médias. Eu ainda gostaria de saber se alguém conhece uma maneira melhor de fazer isso. Obrigado