MySQL8新特性

介绍

MySQL8 的事务性数据字典是相比 MySQL 5.7 的核心改进之一,彻底改变了元数据(如表结构、视图、索引等)的存储和管理方式。

数据库的元数据包含表结构、视图、索引等等数据,在MySQL 5.7之前,元数据存储在文件系统中,这样的存储方式会导致DDL操作不支持事务,即无法做到批量的DDL操作要么完全执行,要么完全不执行。

MySQL 8.0 将默认字符集从 MySQL 5.7 的 latin1 更改为 utf8mb4,并将默认排序规则从 latin1_swedish_ci 更改为 utf8mb4_0900_ai_ci。这一变化显著提升了字符集支持的范围和排序精度。

utf8mb4 是 MySQL 对 UTF-8 的实现,支持完整的 Unicode 字符集,适合存储多语言文本、Emoji 和特殊符号。包括多国语言和补充语言,如 Emoji 和罕见汉字。而latin1仅支持 256 个字符,无法存储 Emoji 或汉字。

而uft8的排序规则utf8mb4_0900_ai_ci 基于 Unicode 9.0 标准,取代了 MySQL 5.7 中的uft8排序规则utf8_general_ci,提供更精确的 Unicode 排序,比较和排序更符合语言习惯(如中文拼音、笔画排序)。

MySQL 5.7也可以设置使用字符集utf8mb4,只不过默认字符集是latin1,但它的utf8排序规则只能是utf8_general_ci,不能使用MySQL 8.0的utf8mb4_0900_ai_ci

在实际开发过程中,我们有时会修改数据库版本,或者将别人的数据库内容导入自己的MySQL中。如果我们导出的数据库版本是MySQL8,现在要将数据导入MySQL5.7当中,往往会出现导入异常。

这大概率就是由于MySQL5.7和MySQL8.0的字符集排序规则和源数据存储方式不同,我们需要打开SQL文件,将建表语句中的字符集和排序规则变成MySQL5.7的规则:

  • COLLATE utf8mb4_0900_ai_ci替换为COLLATE utf8mb4_general_ci
  • ENGINE = InnoDB替换为 ENGINE = MyISAM
  • 去掉表定义末尾的 AUTO_INCREMENT = 1

窗口函数

窗口函数 也叫分析函数 ,用于将查询的结果进行较为复杂的统计分析,MySQL从8.0开始支持窗口函数。

假设我现在有这样一张表:

我想要每个月都统计张三今年的销售总额。也就是这样的一个效果:

此时使用原来的SQL语句,是非常难做到这样的效果的,而要想对查询结果 进行复杂的分析处理,最好的方式就是使用窗口函数

窗口函数中引入了一个窗口 的概念,窗口类似于窗户,限定一个空间范围,或者可以理解为查询结果的自定义集合。而窗口函数可以在处理查询结果的时候,每条结果 都可以结合不同的窗口 ,从而输出相应的数据分析结果。对窗口内数据不同的处理方法 ,可以使用不同的窗口函数。 例如:我们可以查询张三所有月份中最高的销售额

格式:

窗口函数不能过滤查询结果,只能对查询结果进行分析并输出。所以窗口函数是写在SELECT之后,而不是写在WHERE之后。即:

复制代码
SELECT 窗口函数 where 条件

而窗口函数的基本格式如下:

函数名(字段) over(子句)

其中over是关键字,用来指定函数执行的窗口范围,包含三个分析子句:分组(partition by)子句,排序(order by)子句,窗口(rows)子句,如果后面括号中什么都不写,则意味着窗口包含所有的查询结果,窗口函数的完整格式如下:

复制代码
函数名(字段) over(
  partition by <要分组的字段> 
  order by <排序的字段> 
   rows <窗口范围>
)

举个例子:

  1. 向MySQL8数据库中导入销售额表

  2. 查询每个人的销售额,并统计每个月末,每个人的销售总额

    SELECT
    *,
    sum( sales.sales_volume ) over ( -- 计算sales_volume字段的和
    PARTITION BY name -- 根据名字分组
    ORDER BY YEAR(sales.statistical_date),MONTH(sales.statistical_date) -- 根据月份排序
    rows between unbounded preceding and current row -- 窗口范围从之前的所有行到当前行
    ) sum
    FROM
    sales

接下来我们具体介绍一下rows子句的关键字和写法:

  • preceding:前面行
  • following:后面行
  • current row:当前行
  • unbounded:所有行

例如:

  • rows between 2 preceding and current row :窗口取前面两行到当前行
  • rows between unbounded preceding and current row :窗口取之前所有行到当前行
  • rows between current row and unbounded following: 窗口当前行到之后所有行
  • rows between 3 preceding and 1 following:窗口取当前行的前面三行到后面一行,总共五行

如果子句中只有partition by没有order by和rows,窗口规范默认是所有行

如果子句中有order by没有rows,窗口规范默认是取之前所有行到当前行

所以之前的例子也可以这么写:

复制代码
SELECT
    *,
    sum( sales.sales_volume ) over ( -- 计算sales_volume字段的和
        PARTITION BY name -- 根据名字分组
        ORDER BY YEAR(sales.statistical_date),MONTH(sales.statistical_date) -- 根据月份排序
    ) sum 
FROM
    sales 

聚合函数

窗口函数中的聚合函数,负责在窗口内执行聚合计算,支持窗口内累计或统计。常见的聚合函数有这几种:

  • SUM():计算窗口内值的总和
  • AVG():计算窗口内值的平均值
  • COUNT():计算窗口内的行数
  • MIN() :找出窗口内的最小值
  • MAX():找出窗口内的最大值

接下来我们用查询语句举例聚合函数的使用:

复制代码
-- 计算每个销售人员的累计销售额
SELECT 
  *,
  SUM(sales_volume) OVER(PARTITION BY name ORDER BY statistical_date) AS running_total
FROM sales;


-- 计算每个部门的平均销售额
SELECT 
  *,
  AVG(sales_volume) OVER(PARTITION BY department) AS dept_avg_sales
FROM sales;


-- 计算每个销售人员的销售记录数量
SELECT 
  *,
  COUNT(*) OVER(PARTITION BY name) AS sales_count
FROM sales;


-- 找出每个销售人员的最低单月销售额
SELECT 
  *,
  MIN(sales_volume) OVER(PARTITION BY name) AS min_sales
FROM sales;


-- 找出每个销售人员的最高单月销售额
SELECT 
  *,
  MAX(sales_volume) OVER(PARTITION BY name) AS max_sales
FROM sales;

SQL中聚合函数,与窗口函数中聚合函数有什么区别:

我们以同样的需求举例:

复制代码
-- 找出每个销售人员的最高单月销售额
SELECT 
 *,
 MAX(sales_volume) OVER(PARTITION BY name) AS max_sales
FROM sales;


-- 找出每个销售人员的最高单月销售额
SELECT name,SUM(sales_volume) FROM sales GROUP BY name;
  • 普通场景下的聚合函数基于GROUP BY子句定义的组进行计算,将多条记录聚合为一条,只能展示分组字段和聚合函数字段;
  • 窗口函数是基于窗口定义进行计算,每条记录都会执行,而且针对于不同的记录可以设置不同的窗口范围,有几条记录执行完还是几条。

排名函数

排名函数可以为数据集中的行分配排名或序号,常用于排序和比较场景。常见的排名函数有这几种:

  • ROW_NUMBER():为结果集中的每一行分配唯一的连续序号(1, 2, 3...),即使值相同也会分配不同序号
  • RANK():为行分配排名,相同值获得相同排名,但会跳过后续排名(如1,1,3)
  • DENSE_RANK():类似RANK()但不跳过排名数字(如1,1,2)

接下来我们用查询语句举例排名函数的使用:

复制代码
-- 计算3月销售额排名
SELECT 
  *,
        ROW_NUMBER() OVER(ORDER BY sales_volume DESC) AS rn,
        RANK() OVER(ORDER BY sales_volume DESC) AS r,
   DENSE_RANK() OVER(ORDER BY sales_volume DESC) AS dr
FROM sales 
WHERE MONTH(statistical_date) = 3;

分析函数

分析函数用于访问窗口内其他行的数据。常见的分析函数有这几种:

  • LAG(column, n, default):返回当前行前 n 行的 column 列的值,若没有则返回当前行中default列的值。
  • LEAD(column, n, default):返回当前行后 n 行的 column 值,若没有则返回当前行中default列的值。
  • FIRST_VALUE(column):返回窗口内第一行的 column 值。
  • LAST_VALUE(column):返回窗口内最后一行的 column 值。
  • NTH_VALUE(column, n):返回窗口内第 n 行的 column 值。

接下来我们举例分析函数的使用:

复制代码
-- 显示每个销售人员上个月的销售额
-- 显示每个销售人员下个月的销售额
-- 显示每个销售人员第一个月的销售额
-- 显示每个销售人员第二个月的销售额
-- 显示每个销售人员最后一个月的销售额
SELECT 
  *,
   LAG(sales_volume, 1) OVER(
            PARTITION BY name 
            ORDER BY statistical_date 
            rows BETWEEN unbounded preceding AND unbounded following
        ) AS prev_month_sales,
        LEAD(sales_volume, 1 , sales_volume) OVER(
            PARTITION BY name 
            ORDER BY statistical_date
            rows BETWEEN unbounded preceding AND unbounded following
        ) AS next_month_sales,
        FIRST_VALUE(sales_volume) OVER(
            PARTITION BY name 
            ORDER BY statistical_date
            rows BETWEEN unbounded preceding AND unbounded following
        ) AS first_month_sales,
        NTH_VALUE(sales_volume,2) OVER(
            PARTITION BY name 
            ORDER BY statistical_date
            rows BETWEEN unbounded preceding AND unbounded following
        ) AS second_month_sales,
        LAST_VALUE(sales_volume) OVER(
            PARTITION BY name 
            ORDER BY statistical_date
            rows BETWEEN unbounded preceding AND unbounded following
        ) AS last_month_sales
FROM sales;
相关推荐
直有两条腿2 小时前
【Redis】原理-数据结构
数据结构·数据库·redis
学编程就要猛2 小时前
算法:2.复写零
java·数据结构·算法
LYFlied2 小时前
【每日算法】LeetCode238. 除自身以外数组的乘积
数据结构·算法·leetcode·面试·职场和发展
仰泳的熊猫2 小时前
1154 Vertex Coloring
数据结构·c++·算法·pat考试
耶叶2 小时前
查找算法学习总结2:代码分析篇
数据结构·学习·算法
Han.miracle2 小时前
数据库圣经-分析 MySQL 事务隔离级别与并发问题
数据结构·mysql·事务
xu_yule2 小时前
算法基础(区间DP)
数据结构·c++·算法·动态规划·区间dp
biter down2 小时前
C++ 交换排序算法:从基础冒泡到高效快排
c++·算法·排序算法
yyy(十一月限定版)3 小时前
c语言——二叉树
c语言·开发语言·数据结构