MySQL新学知识(一)

MySQL新学知识(一)


前言

👨‍💻👨‍🌾📝记录学习成果,以便温故而知新 本专题把一阶段学到知识MySQL做一个总结


本篇的4项是最近学习的,有的以前可能看到过,但是并没有深入学习了解,这次对照文档稍微深入地学习了一下。在MySQL文档中归属于Built-In Function and Operator Reference和Aggregate Functions下的GROUP BY Modifiers。其中有的功能5.7是支持的,有的功能要到8才支持,需要注意。

一、3个函数

1.COALESCE

MySQL文档https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_coalesce

功能说明如下:

Returns the first non-NULL value in the list, or NULL if there are no non-NULL values.

The return type of COALESCE() is the aggregated type of the argument types.

很简短,意思也不难理解,就不翻译了。

示例如下:

mysql> SELECT COALESCE(NULL,1);

-> 1

mysql> SELECT COALESCE(NULL,NULL,NULL);

-> NULL

也很简短。

以前要是想实现这样的功能,一般都是用 CASE WHEN 来实现的。现在有了COALESCE,很简短。

以上只能说是"一顾倾人城",用在表连接上才是"再顾倾人国"。

假定有x、y与z三个作业表,其中y表的in_id是x表的out_id,z表的in_id是y表的out_id或x表的out_id。

x表结构与数据如下:

sql 复制代码
CREATE TABLE `x` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `in_id` varchar(100) DEFAULT NULL COMMENT '输入ID',
  `out_id` varchar(100) DEFAULT NULL COMMENT '输出ID',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
id in_id out_id
1 T1 T1X1
2 T2 T2X1
3 T2 T2X2
4 T3 T3X1
5 T4 T4X1

y表结构与数据如下:

sql 复制代码
CREATE TABLE `y` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `in_id` varchar(100) DEFAULT NULL COMMENT '输入ID',
  `out_id` varchar(100) DEFAULT NULL COMMENT '输出ID',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
id in_id out_id
1 T1X1 T1X1Y1
2 T2X1 T2X1Y1

y表结构与数据如下:

sql 复制代码
CREATE TABLE `z` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `in_id` varchar(100) DEFAULT NULL COMMENT '输入ID',
  `out_id` varchar(100) DEFAULT NULL COMMENT '输出ID',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
id in_id out_id
1 T1X1Y1 T1X1Y1Z1
2 T3X1 T3X1Z1
3 T4X1 T4X1Z1
4 T4X1 T4X1Z2

对x、y与z表做关联查询SQL如下:

sql 复制代码
SELECT x.id AS X_ID, x.in_id AS X_IN_ID, x.out_id AS X_OUT_ID,
y.id AS Y_ID, y.in_id AS Y_IN_ID, y.out_id AS Y_OUT_ID,
z.id AS Z_ID, z.in_id AS Z_IN_ID, z.out_id AS Z_OUT_ID
FROM x LEFT JOIN y ON x.out_id = y.in_id LEFT JOIN z ON COALESCE(y.out_id, x.out_id) = z.in_id
ORDER BY x.id

查询结果如下图:

对于上述业务模式,COALESCE用在表关联上使得查询语句变得很简洁。

2.GROUP_CONCAT

MySQL文档https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_group-concat

功能说明如下:

This function returns a string result with the concatenated non-NULL values from a group. It returns NULL if there are no non-NULL values

语法如下:

GROUP_CONCAT([DISTINCT] expr [,expr ...]

ORDER BY {unsigned_integer \| col_name \| expr} \[ASC \| DESC\] \[,col_name ...\]

SEPARATOR str_val\]) **The result is truncated to the maximum length that is given by the group_concat_max_len system variable, which has a default value of 1024.**

这里借用下面WITH ROLLUP这节的sales表来举例说明,因为sales是MySQL文档中WITH ROLLUP章节自带的,用在这里也挺合适。

(1)先来一个简单的SQL如下:

sql 复制代码
SELECT year, GROUP_CONCAT(country) AS country
FROM sales
GROUP BY year;

查询结果如下图:

country列中有重复值。

(2)再来一个SQL去掉country列中重复值如下:

sql 复制代码
SELECT year, GROUP_CONCAT(DISTINCT country) AS country
FROM sales
GROUP BY year;

查询结果如下图:

(4)在简单的SQL的基础上根据profit排序如下:

sql 复制代码
SELECT year, GROUP_CONCAT(country ORDER BY profit DESC) AS country
FROM sales
GROUP BY year;

查询结果如下图:

(5)在简单的SQL的基础上先排序后去重如下:

sql 复制代码
SELECT year, GROUP_CONCAT(DISTINCT country ORDER BY country DESC) AS country
FROM sales
GROUP BY year;

查询结果如下图:

3.ROW_NUMBER

MySQL文档https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html#function_row-number

这里还是借用下面WITH ROLLUP这节的sales表来举例说明。

sql 复制代码
SELECT
ROW_NUMBER() OVER w AS 'row_number',sales.*
FROM sales
WINDOW w AS (ORDER BY profit);

查询结果如下图:

效果是有的,但是还需要增加一个"WINDOW",使得语句变得复杂起来了。

二、GROUP聚合的附带功能

1.WITH ROLLUP

MySQL文档https://dev.mysql.com/doc/refman/8.0/en/group-by-modifiers.html

文档中附带一个表用来说明功能。建表语句如下:

sql 复制代码
CREATE TABLE sales
(
    year    INT,
    country VARCHAR(20),
    product VARCHAR(32),
    profit  INT
);

表内容如下:

year country product profit
2000 Finland Computer 1500
2000 Finland Phone 100
2000 India Calculator 150
2000 India Computer 1200
2000 USA Calculator 75
2000 USA Computer 1500
2001 Finland Phone 10
2001 USA Calculator 50
2001 USA Computer 2700
2001 USA TV 250

WITH ROLLUP的功能就是加在GROUP BY子句后生成额外的汇总行,文档中的内容翻译起来感觉很拗口,就直接看下面的效果。

先看不加WITH ROLLUP的效果,语句如下:

sql 复制代码
SELECT year, SUM(profit) AS profit
FROM sales
GROUP BY year;

查询结果如下图:

加WITH ROLLUP的效果,语句如下:

sql 复制代码
SELECT year, SUM(profit) AS profit
FROM sales
GROUP BY year WITH ROLLUP;

查询结果如下图:

与不加WITH ROLLUP相比,多出了一行。

再看一个GROUP BY子句中3列情况,作为对比,先看不加WITH ROLLUP的效果,语句如下:

sql 复制代码
SELECT year, country, product, SUM(profit) AS profit
FROM sales
GROUP BY year, country, product;

查询结果如下图:

加WITH ROLLUP的效果,语句如下:

sql 复制代码
SELECT year, country, product, SUM(profit) AS profit
FROM sales
GROUP BY year, country, product WITH ROLLUP;

查询结果如下图:

与不加WITH ROLLUP相比,多出了8行。

2组查询对比,感觉是GROUP BY子句中的列从右到左,每列在聚合的基础上再汇总。

2.GROUPING

GROUPING是一个函数,配合WITH ROLLUP用的。本文只简单介绍一下WITH ROLLUP文档中部分,更多GROUPING用法请参考GROUPING文档

MySQL文档中如下语句:

sql 复制代码
SELECT
year, country, product, SUM(profit) AS profit,
GROUPING(year) AS grp_year,
GROUPING(country) AS grp_country,
GROUPING(product) AS grp_product
FROM sales
GROUP BY year, country, product WITH ROLLUP;

查询结果如下图:

结果很显然如果参数是null返回1;其它返回0.

感觉作用并不明显,MySQL文档中如下的SQL能够体现出WITH ROLLUP的作用

sql 复制代码
SELECT
IF(GROUPING(year), 'All years', year) AS year,
IF(GROUPING(country), 'All countries', country) AS country,
IF(GROUPING(product), 'All products', product) AS product,
SUM(profit) AS profit
FROM sales
GROUP BY year, country, product WITH ROLLUP;

查询结果如图:

相关推荐
2401_884810742 小时前
Mysql主从复制
数据库·mysql
iuuia2 小时前
16--MySQL使用C语言进行连接
数据库·mysql
zhangfeng11332 小时前
在Cytoscape中安装GeneMANIA插件后相关数据(包括网络数据、物种数据库等)的存储位置,安装目录位置
数据库
Full Stack Developme3 小时前
PostgreSql FDW 与 DBLINK 区别
数据库·postgresql
数字化顾问3 小时前
从索引失效到毫秒级响应——SQL 优化实战案例:从慢查询到高性能的完整指南之电商大促篇
java·开发语言·数据库
小园子的小菜3 小时前
深入剖析 MySQL 中 binlog 与 redolog:区别、联系及在数据更新中的作用
数据库·mysql
李宥小哥5 小时前
C#基础07-类与对象
服务器·数据库·c#
樱木...5 小时前
MySQL 8.0 新特性之原子 DDL
数据库·mysql
1688red5 小时前
MySQL连接时提示ERROR 2002 (HY000)解决方案
数据库·mysql