首页 MySQL LAST_VALUE() 函数

MySQL LAST_VALUE() 函数

MySQL LAST_VALUE() 函数从当前行关联的窗口框架的最后一行中返回评估的值。

LAST_VALUE() 语法

这里是 MySQL LAST_VALUE() 函数的语法:

LAST_VALUE(expr)
OVER (
  [PARTITION BY partition_column_list]
  [ORDER BY order_column_list]
)

参数

expr
必需的。它可以是一个列名或者表达式。
partition_column_list
参与分区的列的列表。
order_column_list
参与排序的列的列表。

返回值

MySQL LAST_VALUE() 函数从当前行关联的窗口框架的最后一行中返回评估的值。

LAST_VALUE() 示例

演示数据准备

使用下面的 CREATE TABLE 语句创建一个表 student_grade 以存储学生的班级和成绩:

CREATE TABLE student_grade (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(50) NOT NULL,
  class CHAR(1) NOT NULL,
  subject VARCHAR(20) NOT NULL,
  grade INT NOT NULL
);

这里创建了一个 student_grade 表,它有 5 个列:

  • id - 行 ID,主键。
  • name - 学生的姓名。
  • class - 学生所在的班级。
  • subject - 科目的名称。
  • grade - 该科目的成绩。

使用下面的 INSERT 语句向 student_grade 表中插入一些行:

INSERT INTO student_grade
  (name, class, subject, grade)
VALUES
  ('Tim', 'A', 'Math', 9),
  ('Tom', 'A', 'Math', 7),
  ('Jim', 'A', 'Math', 8),
  ('Tim', 'A', 'English', 7),
  ('Tom', 'A', 'English', 8),
  ('Jim', 'A', 'English', 7),
  ('Lucy', 'B', 'Math', 8),
  ('Jody', 'B', 'Math', 6),
  ('Susy', 'B', 'Math', 9),
  ('Lucy', 'B', 'English', 6),
  ('Jody', 'B', 'English', 7),
  ('Susy', 'B', 'English', 8);

使用下面的 SELECT 语句检索表中的数据:

SELECT * FROM student_grade;
+----+------+-------+---------+-------+
| id | name | class | subject | grade |
+----+------+-------+---------+-------+
|  1 | Tim  | A     | Math    |     9 |
|  2 | Tom  | A     | Math    |     7 |
|  3 | Jim  | A     | Math    |     8 |
|  4 | Tim  | A     | English |     7 |
|  5 | Tom  | A     | English |     8 |
|  6 | Jim  | A     | English |     7 |
|  7 | Lucy | B     | Math    |     8 |
|  8 | Jody | B     | Math    |     6 |
|  9 | Susy | B     | Math    |     9 |
| 10 | Lucy | B     | English |     6 |
| 11 | Jody | B     | English |     7 |
| 12 | Susy | B     | English |     8 |
+----+------+-------+---------+-------+
12 rows in set (0.00 sec)

按照科目查看每个学生的成绩排名

要查看在每个科目中每个学生按照成绩从高到低的排序号和每个科目中的最好成绩,请使用如下语句:

SELECT 
  *,
  LAST_VALUE(grade) OVER (
    PARTITION BY subject
    ORDER BY grade DESC
    RANGE BETWEEN 
      UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
  ) last_grade
FROM student_grade;
+----+------+-------+---------+-------+------------+
| id | name | class | subject | grade | last_grade |
+----+------+-------+---------+-------+------------+
|  5 | Tom  | A     | English |     8 |          6 |
| 12 | Susy | B     | English |     8 |          6 |
|  4 | Tim  | A     | English |     7 |          6 |
|  6 | Jim  | A     | English |     7 |          6 |
| 11 | Jody | B     | English |     7 |          6 |
| 10 | Lucy | B     | English |     6 |          6 |
|  1 | Tim  | A     | Math    |     9 |          6 |
|  9 | Susy | B     | Math    |     9 |          6 |
|  3 | Jim  | A     | Math    |     8 |          6 |
|  7 | Lucy | B     | Math    |     8 |          6 |
|  2 | Tom  | A     | Math    |     7 |          6 |
|  8 | Jody | B     | Math    |     6 |          6 |
+----+------+-------+---------+-------+------------+
12 rows in set (0.00 sec)

注意,上面 SQL 语句中的窗口函数:

LAST_VALUE(grade) OVER (
  PARTITION BY subject
  ORDER BY grade DESC
  RANGE BETWEEN 
    UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
)

OVER 子句中,

  • PARTITION BY subject 将按照学科进行分区
  • ORDER BY grade DESC 将每个分区内的行按照成绩逆序排列。
  • RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING 定义了每个分区中与当前行相关的窗口框架,这里是从分区的第一行到最后一行。
  • LAST_VALUE(grade) 返回每行在其关联的分区的第一行的成绩(grade)。因为是按照 grade 逆序排序,于是每行中添加了一列显示最差的成绩。

按照班级查看每个学生的总成绩排名

要查看在每个班级中每个学生按照总成绩从高到底的排序号和每个班级的最好成绩,请使用下面的语句:

SELECT 
  t.*,
  LAST_VALUE(t.sum_grade) OVER (
    PARTITION BY class
    ORDER BY t.sum_grade DESC
    RANGE BETWEEN 
      UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
  ) last_grade
FROM (
    SELECT class,
      name,
      sum(grade) sum_grade
    FROM student_grade
    GROUP BY class, name
  ) t;
+-------+------+-----------+------------+
| class | name | sum_grade | last_grade |
+-------+------+-----------+------------+
| A     | Tim  |        16 |         15 |
| A     | Tom  |        15 |         15 |
| A     | Jim  |        15 |         15 |
| B     | Susy |        17 |         13 |
| B     | Lucy |        14 |         13 |
| B     | Jody |        13 |         13 |
+-------+------+-----------+------------+
6 rows in set (0.00 sec)

在上面的语句中,注意这个子查询:

SELECT class,
  name,
  sum(grade) sum_grade
FROM student_grade
GROUP BY class, name

这个子查询使用 GROUP BY 子句和 sum() 按照班级和学生汇总出每个学生的总成绩。

+-------+------+-----------+
| class | name | sum_grade |
+-------+------+-----------+
| A     | Tim  |        16 |
| A     | Tom  |        15 |
| A     | Jim  |        15 |
| B     | Lucy |        14 |
| B     | Jody |        13 |
| B     | Susy |        17 |
+-------+------+-----------+
6 rows in set (0.01 sec)

主语句在从这个子查询中按照班级进行分区,然后在每个分区内按照总成绩逆序排序,并使用 LAST_VALUE(grade) 返回每行在其关联的分区内最后一行中的成绩。

特别声明:本站部分内容收集于互联网是出于更直观传递信息的目的。该内容版权归原作者所有,并不代表本站赞同其观点和对其真实性负责。如该内容涉及任何第三方合法权利,请及时与824310991@qq.com联系,我们会及时反馈并处理完毕。