Itu tidak cantik, tapi saya menemukan solusinya:
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;
Di bagian rekursif dari kueri, alih-alih memanggil GROUP BY
dan menghitung avg(r.rank)
, saya menggunakan fungsi jendela yang dipartisi pada kolom yang sama. Ini memiliki efek yang sama dalam menghitung peringkat rata-rata.
Satu kelemahannya adalah bahwa perhitungan ini terjadi lebih sering daripada yang diperlukan. Jika kita bisa GROUP BY
lalu avg(r.rank)
, itu akan lebih efisien daripada avg(r.rank)
lalu GROUP BY
.
Karena sekarang ada duplikat dalam hasil kueri bersarang, saya menggunakan DISTINCT
untuk menyaring ini dan kemudian kueri luar menghitung RANK()
dari semua atlet di setiap category_id
berdasarkan rata-rata ini.
Saya masih ingin mendengar jika ada yang tahu cara yang lebih baik untuk melakukan ini. Terima kasih