Sql server 2008 MSSQL选择前10名获奖分数,包括平局和每个类别中至少一个

Sql server 2008 MSSQL选择前10名获奖分数,包括平局和每个类别中至少一个,sql-server-2008,Sql Server 2008,我得到了一些帮助,使用以下语句查找前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 要求前10名或前100名(即前100名)中的每个类别至少有一个条目,在这种情况下

我得到了一些帮助,使用以下语句查找前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
要求前10名或前100名(即前100名)中的每个类别至少有一个条目,在这种情况下,有3个类别

现在我需要做的就是在前10名中每个类别至少包含一个条目。i、 e.如果所有前10名的分数都来自类别1,并且有3个类别,我需要删除类别1中的2个最低分数,并包括类别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
EntryID CategoryID  Score
3036    1           85
3159    1           85
3039    1           84
3146    1           83
3019    3           60
3800    2           54
______________________
Total Entries >= 6
同样的事情也发生在下面的场景中,让我们看看前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
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
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
请原谅,如果我重复我自己的话,我只是想让你明白


我真的很感谢你的帮助

如我所见,您需要以更复杂的方式对行进行排序,以便在每个类别中排名靠前的条目都会被包括在内,而不管它们的值如何,而不是排名靠前的条目则会根据它们的总体排名被包括在内

我将要提出的可能不是最有效的解决方案,但它应该有效,如果没有其他办法,可能会激励其他人想出更好的解决方案:

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的下一步是获得全球排名,这一次要考虑一个条目是否是其类别中的顶级条目。类别顶级值的排名较低,因此确保包含在最终结果中。当然,您需要确保类别的数量不大于您希望在输出中接收的不同值的数量


这里有一个例子。

在前五名的例子中,为什么你希望有四个1类条目而不是三个?@Juhana:这里有三个前五名的例子。你可能应该更具体地说你在谈论哪一个。前两个是将前5个值中的一个值的两个条目替换为来自不同类别的另一个值的条目。最后一个问题是,当表中没有其他类别,但前5名中已经包含的类别时,保持条目不变。Hi@Juhana,如果你查看分数,你会注意到EntryID的3036和3159,例如,它们是相同的,即平局。如果你按分数分组,你会看到只有5分,即85分、84分、83分、82分和60分。通常的惯例是,领带只在列表的末尾起作用,也就是说,如果前两个分数相同,他们都是第一名,但下一个是第三名,在这种情况下就没有第二名了,所以这就把我甩了。@Juhana:不,实际上所有的领带都算作单个值。你可以在每个例子中看到这一点。特别是前五名,总是包含5个不同的值。谢谢,这似乎很有用。。。排名对我来说是新的,我仍然觉得有点困惑,但我正在学习。谢谢你的时间!哦,是的,谢谢你的提醒-即猫的数量不超过不同值的数量…@Iant22:很高兴能提供帮助!我有一些计划来重温这个问题,并在白天找到解决它的方法。但是你瞧,你找到了完全相同的解决方案+1.@MikaelEriksson:谢谢!我仍然认为有更好的解决办法。排名函数是很好的工具,我非常喜欢它们,只是事实上可能太喜欢了。其他更有效的解决方案对我来说就不那么明显了。