我得到了一些帮助,使用以下声明
找到前10个分数,包括并列条目select T.EntryID, T.CategoryID, T.Score
from (
select EntryID, CategoryID, Score,
dense_rank() over(order by Score) as rn
from YourTable
) T
where T.rn <= 10
(谢谢[mikael-eriksson]:https://stackoverflow.com/users/569436/mikael-eriksson)
[问题]:MSSQL Selecting top 10 but include columns with duplicate values以下是示例数据:
EntryID CategoryID Score
3036 1 85
3159 1 85
3039 1 84
3146 1 83
3225 1 82
3045 1 82
3047 1 80
3048 1 80
3049 1 80
3193 1 80
3098 1 80
3025 1 72
3082 1 70
3167 1 70
3122 1 67
3220 1 65
3080 1 65
3168 1 64
______________________
Total Entries >= 18
要求前10名中的每个类别至少有一个条目(或者不论它是什么,即前100名),在这种情况下有3个类别。
现在我需要做的就是在前10名中每个类别至少包含一个条目。即,如果前10个分数都来自第1类,并且有3个类别,我需要从中删除2个最低分数第1类,包括第2类和第3类的最高分数。
从结果中可以看出,所有条目都来自类别1,因此我需要从结果集中删除EntryID的3220,3080和3168,因为它们是得分最低的,并且还包括类别2中得分最高的条目作为第3类中得分最高的条目,结果看起来像这样:
EntryID CategoryID Score
3036 1 85
3159 1 85
3039 1 84
3146 1 83
3225 1 82
3045 1 82
3047 1 80
3048 1 80
3049 1 80
3193 1 80
3098 1 80
3025 1 72
3082 1 70
3167 1 70
3122 1 67
3019 3 60
3800 2 54
______________________
Total Entries >= 17
同样的情况适用于以下场景,让我们看一下前5个而不是前10个,以便让它更容易一些,正如您在本例中所见,前5个分数排除了类别2中的条目
EntryID CategoryID Score
3036 1 85
3159 1 85
3039 1 84
3146 1 83
3225 1 82
3045 1 82
3019 3 60
______________________
Total Entries >= 7
在这种情况下,条目3225和3045需要删除,因为它们是得分最低的条目(需要包括3047,即使它是得分最低的条目我需要结果中所有类别的条目)我需要包括来自第2类的得分最高的参赛作品,我希望这样:
EntryID CategoryID Score
3036 1 85
3159 1 85
3039 1 84
3146 1 83
3019 3 60
3800 2 54
______________________
Total Entries >= 6
然后可能存在可能没有进入特定类别的情况,例如没有类别2条目,因此结果应该仍然具有前5个与前5个的原始结果集一样(包括在下面作为参考)
EntryID CategoryID Score
3036 1 85
3159 1 85
3039 1 84
3146 1 83
3225 1 82
3045 1 82
3019 3 60
______________________
Total Entries >= 7
请原谅我是否在重复自己,我只是想说清楚理解;)
我非常感谢您的帮助!
答案 0 :(得分:8)
正如我所看到的,您需要以更复杂的方式对行进行排名,以便包含每个类别中最重要的条目而不管它们的值如何,并且根据条目包含不是顶级条目的条目他们的整体排名。
我要提出的建议可能不是最有效的解决方案,但它应该有效,如果没有别的办法,可能会激励其他人提出更好的解决方案:
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按类别对行进行排名,从而让我们找出哪些条目成为各自类别中的顶级条目。下一步(第二次CTE)是关于获得全球排名,这次考虑一个条目是否是其类别中的最高级别。类别最高值获得较低排名,因此确保包含在最终结果中。 (当然,您需要确保类别数量不大于您希望在输出中接收的不同值的数量。)
这是一个live example at SQL Fiddle来玩。