Như tôi thấy, bạn cần phải xếp hạng các hàng của mình theo cách phức tạp hơn, để các mục nhập đứng đầu trong mọi danh mục được đưa vào bất kể giá trị của chúng và các mục nhập không phải là hàng đầu được bao gồm theo tổng thể của chúng thứ hạng.
Những gì tôi sắp đề xuất có thể không phải là giải pháp hiệu quả nhất, nhưng nó sẽ hoạt động và nếu không có gì khác có thể làm được, có thể truyền cảm hứng cho người khác nghĩ ra điều gì đó tốt hơn:
WITH ranked1 AS (
SELECT
*,
RankByCategory = DENSE_RANK() OVER (
PARTITION BY CategoryID
ORDER BY Score DESC
)
FROM YourTable
),
ranked2 AS (
SELECT
*,
FinalRank = DENSE_RANK() OVER (
ORDER BY
CASE RankByCategory WHEN 1 THEN 1 ELSE 2 END,
Score DESC
)
FROM ranked1
)
SELECT
EntryID,
CategoryID,
Score
FROM ranked2
WHERE FinalRank <= @top_n
;
CTE đầu tiên là xếp hạng các hàng theo danh mục, do đó cho phép chúng tôi tìm hiểu mục nhập nào trở thành mục hàng đầu trong danh mục tương ứng của chúng. Bước tiếp theo (CTE thứ hai) là đạt được thứ hạng toàn cầu, lần này là tính đến việc một mục nhập có phải là mục đứng đầu trong danh mục của nó hay không. Các giá trị hàng đầu của danh mục nhận được thứ hạng thấp hơn và do đó được đảm bảo đưa vào kết quả cuối cùng. (Tất nhiên, bạn cần đảm bảo rằng số danh mục không lớn hơn số giá trị riêng biệt mà bạn muốn nhận trong đầu ra.)
Đây là ví dụ trực tiếp tại SQL Fiddle để chơi với.