mysql分析函数和开窗函数的区别
时间: 2024-08-13 20:08:16 浏览: 143
MySQL中的分析函数(Analytic Functions)和开窗函数(Window Functions)都是用来处理集合并提供上下文相关的数据处理的功能,但它们在使用场景和功能上有所区别。
**分析函数**:
1. 分析函数主要用于单行计算,对当前行进行操作,但不考虑整个分区或窗口。它们通常在GROUP BY语句之后使用,比如RANK(), ROW_NUMBER()等,用于为分组结果排序或生成唯一标识。
2. 它们的计算基于每个行的值,而不会跨越行,不会创建窗口。
3. 每次查询只返回一行,不支持跨行的操作。
**开窗函数**:
1. 开窗函数(也叫窗口函数或窗口函数)则是在每个窗口(由PARTITION BY或ROW_NUMBER等定义)内进行计算,每行都有一个相对的上下文,即窗口内的其他行。这使得它们能够处理基于整个子集的数据,如求和、平均值或排名。
2. 窗口函数通常在OVER()子句中指定,它可以跨越多行,适用于需要在一定范围内进行累计计算(如移动平均)或排名(如每一行在其前面行的基础上得到排名)的情况。
3. 查询结果可能包含多行,因为它们会返回整个窗口内的计算结果。
相关问题
oracle 开窗函数 和mysql 开窗函数 有什么区别
Oracle 和 MySQL 的窗口函数有以下区别:
1. 语法不同:Oracle 和 MySQL 窗口函数的语法略有不同。Oracle 使用 OVER 子句来指定分析函数,而 MySQL 使用 OVER() 子句。
2. 支持的函数不同:Oracle 支持的分析函数比 MySQL 更多。例如,Oracle 支持 RANK()、DENSE_RANK() 和 ROW_NUMBER() 函数,而 MySQL 不支持这些函数。
3. 窗口帧的默认值不同:Oracle 和 MySQL 窗口函数的默认窗口帧不同。Oracle 默认使用 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW,而 MySQL 默认使用 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW。
4. 处理 NULL 值的方式不同:Oracle 和 MySQL 在处理 NULL 值时有所不同。Oracle 中的分析函数忽略 NULL 值,而 MySQL 中的分析函数将 NULL 视为最小值。
总之,虽然 Oracle 和 MySQL 的窗口函数有一些不同之处,但它们的基本作用和用法是相似的,都是用于分析和处理查询结果集。
MYSQL 开窗函数
### 使用开窗函数在 MySQL 中实现累加
自 MySql 8.0 版本起引入了对开窗函数的支持,这使得执行复杂的分析操作变得更加简便。开窗函数允许在一个查询的结果集上定义窗口或分区,并在此基础上计算聚合值而不影响原始表的数据[^1]。
#### 基础语法结构
开窗函数的一般形式如下:
```sql
function_name([expression]) OVER ([partition_clause] [order_by_clause])
```
其中 `function_name` 是指支持作为开窗函数使用的特定 SQL 函数;`OVER()` 子句用于指定要应用此功能的数据范围以及排序方式。
#### 实际案例展示
考虑一个聊天记录表 (`chat_history`) 的场景,在这里想要获取每一对对话者之间最新的未读消息数量。可以利用 ROW_NUMBER() 这样的开窗函数来完成这一需求:
```sql
WITH RankedMessages AS (
SELECT
from_id,
to_id,
msg,
isRead,
time,
ROW_NUMBER() OVER(PARTITION BY from_id, to_id ORDER BY time DESC) as rn
FROM chat_history
)
SELECT *
FROM RankedMessages
WHERE rn = 1 AND isRead = 0;
```
上述代码通过 PARTITION BY 对话双方 ID 创建分组,并按照时间降序排列每条消息,最后只保留每个会话里最新一条的消息并筛选出那些尚未被阅读过的项。
对于更早版本如 MySQL 5.7 并不支持这些特性,则需采用用户变量的方法模拟类似行为[^2]:
```sql
SELECT * FROM (
SELECT
CASE WHEN @prev <> CONCAT(from_id,to_id) THEN @rn := 1 ELSE @rn := @rn + 1 END AS rownum,
@prev := CONCAT(from_id,to_id),
ch.*
FROM chat_history ch,
(SELECT @rn := 0, @prev := '') vars
WHERE ...
ORDER BY from_id, to_id, time DESC
) subq
WHERE rownum = 1;
```
这段脚本同样实现了按发信人和收件人的组合进行编号的功能,但是采用了不同的技术手段。
阅读全文
相关推荐
















