SQL之排名窗口函数RANK()、ROW_NUMBER()、DENSE_RANK() 和 NTILE() 的区别(SQL 和 Hive SQL 都支持)
现有一张student 表,表中包含id、uname、age、score 四个字段,如下所示:
该表的数据如下所示:
一、ROW_NUMBER()
1、概念
ROW_NUMBER() 为结果集中的每一行分配一个唯一的连续整数,编号从 1 开始。 该函数按照指定的顺序进行排序,即使存在相同的值,每一行也会获得不同的编号。例如,如果有两个排名为 1 的值,下一个值将会被标记为 3
2、示例
对student表中的score列使用ROW_NUMBER()进行排序,排序语句如下;
SELECT
s.id,
s.uname,
s.age,
s.score,
ROW_NUMBER() OVER(ORDER BY s.score desc) as higher_score
FROM student s;
执行结果如下所示:
注意:他一般不能用于排名问题,因为对于相同的分数,排名是不同的。
二、RANK()
1、概念
RANK() 为结果集中的每一行分配一个整数,表示其在排序中的相对位置。 如果存在相同的值,RANK() 会将这些值分配相同的排名,并且下一个排名会跳过相应的数量。例如,如果有两个排名为 1 的值,下一个值将会被标记为 3。
2、示例
对student表中的score列使用 RANK() 进行排序,排序语句如下;
SELECT
s.id,
s.uname,
s.age,
s.score,
RANK() OVER(ORDER BY s.score desc) as rank_no
FROM student s;
执行结果如下所示:
三、DENSE_RANK()
1、概念
DENSE_RANK() 与 RANK() 类似,也为相同的值分配相同的排名,但它不会跳过数字。 因此,DENSE_RANK() 的排名是连续的,而 RANK() 的排名是不连续的。
2、示例
对student表中的score列使用 DENSE_RANK() 进行排序,排序语句如下;
SELECT
s.id,
s.uname,
s.age,
s.score,
DENSE_RANK() OVER(ORDER BY s.score desc) as dense_rank_no
FROM student s;
执行结果如下所示:
四、NTILE()
1、概念
NTILE()函数是一种窗口函数,用于将每个窗口分区的行分割为从1到至多n的n个桶。
2、原理
ntile函数可以将有序的数据集合平均分配到指定的桶中。如果不能平均分配,较小的桶会分配额外的行,并且各个桶中能放的行数最多相差1。例如,如果桶的数量为4,总共有6行数据,分配结果如下:
桶1:1行、2行
桶2:3行、4行
桶3:5行
桶4:6行
这样确保了每个桶中的数据量尽可能均衡。
3、示例
(1)代码1:
SELECT
s.id,
s.uname,
s.age,
s.score,
NTILE(1) OVER(ORDER BY s.score desc) as ntile_no
FROM student s;
(2)代码1运行结果:
(3)代码2:
SELECT
s.id,
s.uname,
s.age,
s.score,
NTILE(2) OVER(ORDER BY s.score desc) as ntile_no
FROM student s;
(4)代码2运行结果:
(5)代码3:
SELECT
s.id,
s.uname,
s.age,
s.score,
NTILE(3) OVER(ORDER BY s.score desc) as ntile_no
FROM student s;
(6)代码 3运行结果:
(7)代码 4:
SELECT
s.id,
s.uname,
s.age,
s.score,
NTILE(4) OVER(ORDER BY s.score desc) as ntile_no
FROM student s;
(8)代码 4运行结果: