Не е красиво, но намерих решение:
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;
В рекурсивната част на заявката, вместо да извиквате GROUP BY
и изчисляване на avg(r.rank)
, използвам функция за прозорец, разделена на същите колони. Това има същия ефект при изчисляването на средния ранг.
Един недостатък е, че това изчисление се случва повече пъти, отколкото е необходимо. Ако можехме GROUP BY
след това avg(r.rank)
, това би било по-ефективно от avg(r.rank)
след това GROUP BY
.
Тъй като вече има дубликати в резултата от вложената заявка, използвам DISTINCT
за да ги филтрирате и след това външната заявка изчислява RANK()
от всички спортисти във всеки category_id
въз основа на тези средни стойности.
Все пак ще се радвам да чуя дали някой знае по-добър начин за това. Благодаря