CodeGym /课程 /SQL SELF /主要窗口函数: ROW_NUMBER()RANK()、...

主要窗口函数: ROW_NUMBER()RANK()DENSE_RANK()NTILE()

SQL SELF
第 29 级 , 课程 1
可用

上一节我们已经明白了窗口函数到底有啥用。现在来看看具体的函数和它们的效果。语法细节我们下节再说。

ROW_NUMBER() 函数

ROW_NUMBER() 函数会给窗口里的每一行分配一个唯一的编号。就是按 ORDER BY 指定的顺序给每行排个号。

语法:

ROW_NUMBER() OVER ([PARTITION BY column] ORDER BY column)

解释一下:

  • PARTITION BY column(可选):把数据分组。如果不写,就是全表一起编号。
  • ORDER BY column:指定按哪个字段排序来编号。

例子:给表里的行编号

来看一张 students 表,里面有学生和他们的分数。

SELECT * FROM students;
id name score
1 Eva Lang 95
2 Maria Chi 87
3 Alex Lin 78
4 Anna Song 95
5 Otto Mart 87

现在我们按分数(score)从高到低给每行排个号:

SELECT
    name, 
    score, 
    ROW_NUMBER() OVER (ORDER BY score DESC) AS row_num
FROM students;

结果:

name score row_num
Eva Lang 95 1
Anna Song 95 2
Maria Chi 87 3
Otto Mart 87 4
Alex Lin 78 5

每一行都拿到了唯一的序号——而且是按分数从高到低排的。

这个操作其实很简单但很强大——直接在查询结果里加个行号。用传统 SELECT 根本做不到,必须用窗口函数才行。

RANK() 函数

RANK()ROW_NUMBER() 很像,但它会考虑相同的值。如果有几行排序字段一样,它们会拿到一样的排名,后面的排名会跳过。

语法:

RANK() OVER ([PARTITION BY column] ORDER BY column)

例子:按分数给学生排名

我们用 RANK() 来试试同样的数据:

SELECT
    name, 
    score, 
    RANK() OVER (ORDER BY score DESC) AS rank
FROM students;

结果:

name score rank
Eva Lang 95 1
Anna Song 95 1
Maria Chi 87 3
Otto Mart 87 3
Alex Lin 78 5

这里分数一样的行(9587)拿到一样的排名,后面的排名就跳过了。

DENSE_RANK() 函数

DENSE_RANK()RANK() 差不多,但排名不会跳号。也就是说有重复的行,后面的排名只会加 1。

语法:

DENSE_RANK() OVER ([PARTITION BY column] ORDER BY column)

例子:紧密排名

我们用 DENSE_RANK() 试试同样的数据:

SELECT
    name, 
    score, 
    DENSE_RANK() OVER (ORDER BY score DESC) AS dense_rank
FROM students;

结果:

name score dense_rank
Eva Lang 95 1
Anna Song 95 1
Maria Chi 87 2
Otto Mart 87 2
Alex Lin 78 3

这里和 RANK() 不一样,排名是连续的,没有跳号。

NTILE() 函数

NTILE() 会把行分成 n 个均匀的组(分位),每行分到一个组里。

语法:

NTILE(n) OVER ([PARTITION BY column] ORDER BY column)
  • n:你想分成几组。

例子:把学生分成 3 组

我们把学生按分数从高到低分成 3 组:

SELECT
    name, 
    score, 
    NTILE(3) OVER (ORDER BY score DESC) AS group_num
FROM students;

结果:

name score group_num
Eva Lang 95 1
Anna Song 95 1
Maria Chi 87 2
Otto Mart 87 2
Alex Lin 78 3

注意:如果不能完全均分,多出来的行会优先分到前面的组。比如这里前两组各有两个人,最后一组只有一个。

什么时候用哪个函数?

  • ROW_NUMBER():想给每行唯一编号时用,按排序顺序来。
  • RANK():需要考虑相同值排名,并且允许排名跳号时用。
  • DENSE_RANK():考虑相同值排名,但排名不跳号时用。
  • NTILE():想把行均匀分组时用。

这些函数能让你分析数据的方式直接升级。只要你需要灵活地给数据编号或者分组,窗口函数都能帮上大忙。

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION