SQL中的高级函数

SQL中的高级函数

学会了SQL的语法以及一些基础的常用函数已经可以完成大多数的业务操作,而学习高级函数也是在一个进阶过程。如分析函数,数值函数,加密函数

分析函数

MySQL 中的分析函数是指用于在查询结果中进行分析和计算的函数。常见的 MySQL 分析函数包括:

  1. ROW_NUMBER(): 返回结果集中行的排名。
  2. RANK(): 计算结果集中行的排名,如果有相同的数值,则会跳过相同的排名。
  3. DENSE_RANK(): 计算结果集中行的排名,如果有相同的数值,则会按照顺序进行排名,不会跳过。
  4. NTILE(n): 将结果集均匀地分成 n 份,并返回每行所在的组别。
  5. LEAD(expr, offset, default): 返回结果集中当前行之后第 offset 行的 expr 列的值,如果超出结果集范围,则返回 default。
  6. LAG(expr, offset, default): 返回结果集中当前行之前第 offset 行的 expr 列的值,如果超出结果集范围,则返回 default。

mysql从8.0引入了窗口函数,通过 OVER 子句来指定窗口的范围和排序规则,并可以在查询结果中进行分组、排名和聚合等操作。

ROW_NUMBER函数

为结果集中每一行分配一个行号。

语法如下

SELECT column1, column2, ..., ROW_NUMBER() OVER (ORDER BY column ASC|DESC) AS row_number
FROM table_name;

示例如下

SELECT name, age, ROW_NUMBER() OVER (ORDER BY age DESC) AS row_number
FROM students;

解释如下

这个查询会返回 students 表中每个学生的姓名和年龄,并为每个学生分配一个按年龄降序排列的行号。

name    | age | score
----------------------
Alice   | 18  | 90
Bob     | 19  | 85
Charlie | 20  | 90
Dave    | 18  | 80
Eva     | 21  | 70
Frank   | 22  | 60
Gina    | 19  | 50
Henry   | 20  | 40
Ivy     | 19  | 30

name    | age | row_number
--------------------------
Frank   | 22  | 1
Eva     | 21  | 2
Charlie | 20  | 3
Henry   | 20  | 4
Bob     | 19  | 5
Gina    | 19  | 6
Alice   | 18  | 7
Dave    | 18  | 8
Ivy     | 17  | 9
RANK函数

为结果集中的每一行分配一个排名。

语法如下

SELECT column1, column2, ..., RANK() OVER (ORDER BY column ASC|DESC) AS rank
FROM table_name;

示例如下

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

解释如下

这个查询会返回 students 表中每个学生的姓名和分数,并为每个学生分配一个按照分数降序排列的排名。如果有两个学生的分数相同,它们将被分配相同的排名,并且下一个排名将会被跳过。这意味着可能会存在不连续的排名

name    | score
----------------
Alice   | 90
Bob     | 85
Charlie | 90
Dave    | 80
Eva     | 70
Frank   | 60
Gina    | 50
Henry   | 40
Ivy     | 30

name    | score | rank
-----------------------
Alice   | 90    | 1
Charlie | 90    | 1
Bob     | 85    | 3
Dave    | 80    | 4
Eva     | 70    | 5
Frank   | 60    | 6
Gina    | 50    | 7
Henry   | 40    | 8
Ivy     | 30    | 9
DENSE_RANK函数

类似于 RANK() 函数,用于为结果集中的每一行分配一个排名,不同之处在于 DENSE_RANK() 不会出现重复的排名。

语法如下

SELECT column1, column2, ..., DENSE_RANK() OVER (ORDER BY column ASC|DESC) AS dense_rank
FROM table_name;

示例如下

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

解释如下

这个查询会返回 students 表中每个学生的姓名和分数,并为每个学生分配一个按照分数降序排列的稠密排名。会为相同的排序值分配相同的排名,并在跳过相同排名后继续分配连续的排名。这意味着排名是稠密的且连续的,不会出现空缺。

name    | score
----------------
Alice   | 90
Bob     | 85
Charlie | 90
Dave    | 80
Eva     | 70
Frank   | 60
Gina    | 50
Henry   | 40
Ivy     | 30

name    | score | dense_rank
----------------------------
Alice   | 90    | 1
Charlie | 90    | 1
Bob     | 85    | 2
Dave    | 80    | 3
Eva     | 70    | 4
Frank   | 60    | 5
Gina    | 50    | 6
Henry   | 40    | 7
Ivy     | 30    | 8
NTILE函数

用于将结果集划分为指定数量的桶,并为每个桶分配一个标识符。

语法如下

SELECT column1, column2, ..., NTILE(n) OVER (ORDER BY column ASC|DESC) AS bucket
FROM table_name;

示例如下

SELECT name, score, NTILE(4) OVER (ORDER BY score DESC) AS bucket
FROM students;

解释如下

这个查询会返回 students 表中每个学生的姓名和分数,并将结果集划分为4个桶,按照分数降序排列,同时为每个桶分配一个标识符。

name    | score
----------------
Alice   | 90
Bob     | 85
Charlie | 90
Dave    | 80
Eva     | 70
Frank   | 60
Gina    | 50
Henry   | 40
Ivy     | 30

name    | score | bucket
--------------------------
Alice   | 90    | 1
Charlie | 90    | 1
Bob     | 85    | 2
Dave    | 80    | 2
Eva     | 70    | 3
Frank   | 60    | 3
Gina    | 50    | 4
Henry   | 40    | 4
Ivy     | 30    | 4
LEAD函数

用于访问结果集中当前行之后的行的数据。具体来说,LEAD() 函数可以访问指定偏移量后的行,并返回该行指定列的值。

语法如下

LEAD(column, offset, default) OVER (ORDER BY column ASC|DESC)

示例如下

SELECT name, score, LEAD(score, 1, 0) OVER (ORDER BY score DESC) AS next_score
FROM students;

解释如下

这个查询会返回 students 表中每个学生的姓名和分数,以及每个学生后面一个学生的分数。在这个例子中,LEAD(score, 1, 0) 表示获取当前行之后一行的分数值,如果没有下一行,则返回默认值0。同时,我们按照分数降序排列结果集。

name    | score
----------------
Alice   | 90
Bob     | 85
Charlie | 90
Dave    | 80

name    | score | next_score
----------------------------
Alice   | 90    | 85
Charlie | 90    | 85
Bob     | 85    | 80
Dave    | 80    | 0
LAG函数

用于访问前一行的数据的窗口函数。它可以帮助你在结果集中获取前一行的数值,从而进行比较或计算增量等操作。

语法如下

LAG (expression, offset, default) OVER ( [partition_by_clause] order_by_clause )

示例如下

SELECT  name,  age, 
  LAG(age, 1, 0) OVER (ORDER BY name) AS prev_age,
  age - LAG(age, 1, 0) OVER (ORDER BY name) AS age_difference
FROM students;

解释如下

通过使用 LAG 函数,我们得到了每个学生与前一个学生的年龄差值。

name    | age
------------
Alice   | 18
Bob     | 19
Charlie | 20
Dave    | 21
Eva     | 22

name    | age | prev_age | age_difference
----------------------------------------
Alice   | 18  | 0        | 18
Bob     | 19  | 18       | 1
Charlie | 20  | 19       | 1
Dave    | 21  | 20       | 1
Eva     | 22  | 21       | 1

窗口帧

用于定义窗口函数计算范围的一种语法。这也意味着它是跟随窗口函数一块出现的。

常用语法

[ROWS/RANGE] BETWEEN <start> AND <end>

参数

  • ROWSRANGE 用于指定窗口帧的类型,ROWS 表示基于行的帧,RANGE 表示基于值的帧。
  • <start><end> 用于指定窗口帧的起始和结束位置。

常用的窗口帧包括

  • ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW:从查询结果集的第一行到当前行。
  • ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING:从当前行到查询结果集的最后一行。
  • ROWS BETWEEN x PRECEDING AND y FOLLOWING:从当前行向前 x 行,并从当前行向后 y 行。

举例说明

SELECT 
  order_id,
  order_date,
  total_amount,
  SUM(total_amount) OVER (
    ORDER BY order_date
    ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
  ) AS cumulative_total
FROM orders;

解释

这个查询将计算每个订单及其前面所有订单的累计金额,并将结果作为一个新的列 cumulative_total 返回。

order_id | order_date | total_amount
-----------------------------------
1        | 2023-01-01 | 100
2        | 2023-02-01 | 200
3        | 2023-03-01 | 300
4        | 2023-04-01 | 400
5        | 2023-05-01 | 500

order_id | order_date | total_amount | cumulative_total
------------------------------------------------------
1        | 2023-01-01 | 100          | 100
2        | 2023-02-01 | 200          | 300
3        | 2023-03-01 | 300          | 600
4        | 2023-04-01 | 400          | 1000
5        | 2023-05-01 | 500          | 1500
  • 36
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值