GROUP BY TOP N应用场景

因为工作原因,前段时间遇到这样的问题游戏角色合服,但是每个区服下同一个账号只能保留3个角色,那么问题来了,挖掘机技术那家强?

可能有的同学还是没明白这是怎样的应用场景,举个例子:

GROUP BY TOP N应用场景_第1张图片

上面数据场景从,现在要求单科前两名同学的成绩。

现在怎么来解决这样的问题?

通过分析可知,我们现在是要在每一科两面找到前2位成绩排名的信息。

很遗憾的告诉大家,其实Oracle和MSSQL都是有自带函数rownumber() over(partition by col1 order by col2)

   row_number()和rownum差不多,功能更强一点(可以在各个分组内从1开时排序);

   rank()是跳跃排序,有两个第二名时接下来就是第四名(同样是在各个分组内);

   dense_rank()l是连续排序,有两个第二名时仍然跟着第三名。相比之下row_number是没有重复值的.

MySQL好像还没这样的函数,Over函数都没,如果你愿意的话可以写了一个Over函数,但是这里就不讨论了,我只说一个能直接查询的语句。

GROUP BY TOP N应用场景_第2张图片

SELECT * FROM (    select *,@num := if(@group = `course`, @num + 1, 1) as row_number,@group := course as sub_group
    from Points order by course,point desc)    as x
WHERE x.row_number<=2;

SQL中有几点要给大家说明一下@num相当于我们自己给的一个排序码,然后这个排序码是根据sub_group来分隔的,也就是说一个group里面都有一个唯一不重复的排序码,有了这个排序码过后我们最后在这个大的结果集里面就可以用这个排序码作为前几名同学的筛选条件出最后的数据了。

注意一点,这里在每个分组里面的我的排序码是全自增的,没有实现前面rank()和dense_rank()这样的功能。


既然都说了MSSQL有这样的函数总要拉出来溜溜啥。

GROUP BY TOP N应用场景_第3张图片GROUP BY TOP N应用场景_第4张图片

SELECT [name],[course],[point]
FROM
(SELECT [name],[course],[point],
ROW_NUMBER() OVER ( PARTITION BY [course] ORDER BY [point] DESC ) AS RowNumber
FROM [dbo].[Points]) AS X
WHERE X.RowNumber<=2

这个主题就讨论到此,有交流或者有更好实现方法的同学一定@我额。





你可能感兴趣的:(数据库)