Nó không đẹp, nhưng tôi đã tìm ra giải pháp:
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;
Trong phần đệ quy của truy vấn, thay vì gọi GROUP BY
và tính toán avg(r.rank)
, Tôi sử dụng một hàm cửa sổ được phân vùng trên các cột giống nhau. Điều này cũng có tác dụng tương tự trong việc tính toán xếp hạng trung bình.
Một nhược điểm là tính toán này xảy ra nhiều lần hơn mức cần thiết. Nếu chúng ta có thể GROUP BY
rồi đến avg(r.rank)
, điều đó sẽ hiệu quả hơn avg(r.rank)
rồi đến GROUP BY
.
Vì hiện có các bản sao trong kết quả của truy vấn lồng nhau, tôi đang sử dụng DISTINCT
để lọc những thứ này ra và sau đó truy vấn bên ngoài sẽ tính toán một RANK()
của tất cả các vận động viên trong mỗi category_id
dựa trên các mức trung bình này.
Tôi vẫn muốn nghe nếu có ai biết cách tốt hơn để làm điều này. Cảm ơn