2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序

玲珑骰(tou)子安红豆,入骨相思知不知?

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第1张图片

骰子(tóu zi),又称色子(shǎi zi)

一、ORDER  BY 排序

使用ORDER BY查询到的数据进行排序操作。

1、没有指定排序(即没有使用关键字ORDER BY),则查询的数据默认的顺序是:数据库中数据添加的先后顺序。如下:

SELECT * FROM `employees`;

2、DESC  降序,如果在ORDER BY后没有显式指定排序的方式的话,默认升序ASC

DESC是DESCENDING的缩写,ASC是ASCENDING的缩写。缩写和不缩写都可以使用。

SELECT `employee_id`,`first_name`,`salary` FROM `employees`ORDER BY `salary`;

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第2张图片

3、 二级排序,如果第 1 个字段相等,则按第 2 个字段排序,依次类推。

在对多列进行排序的时候,首先排序的第一列必须有相同的列值,才会对第二列进行排序。如果第一列数据中所有值都是唯一的,将不再对第二列进行排序。

#按照工资降序排列,工资相同则按照姓名升序排列
SELECT `last_name`,`salary` 
FROM `employees`
ORDER BY `salary` DESC, `last_name` ASC;

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第3张图片

4、列的别名可以在ORDER BY中使用不能在WHERE 中使用

1.正确SQL示范

#按照工资降序排列,工资相同则按照姓名升序排列
SELECT `last_name`,`salary` ,salary * 10 sals
FROM `employees` 
ORDER BY sals;

======

2.错误SQL演示

#列的别名在where中使用会报错
SELECT `last_name`,`salary` ,salary * 10 sals
FROM `employees` 
WHERE sals>100;

报错如下:Unknown column 'sals' in 'where clause'

之所以报错和sql的执行流程有关。。在本篇文章最后有


二、GROUP BY 分组

分组允许把数据分为多个逻辑组,以便能对每个组进行聚集计算

SELECT中出现的非聚合函数字段必须出现在GROUP BY子句中。反之,GROUP BY中声明的字段可以不出现在SELECT中。

# 查询整个公司的平均工资,就只能查询出来一条记录
SELECT AVG(salary) FROM employees;

#查询各个部门的平均工资
SELECT department_id,AVG(salary) FROM employees
GROUP BY department_id;

#查询各个工种的平均工资
SELECT job_id,AVG(salary) FROM employees
GROUP BY job_id;

多列分组,查询各个部门每个工种的平均工资。

#多列分组,查询各个部门各个工种的平均工资
SELECT department_id,job_id,AVG(salary) FROM employees
GROUP BY department_id,job_id
ORDER BY department_id DESC;

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第4张图片


三、HAVING  聚合条件过滤

HAVING的使用是依托于GROUP BY

#在使用HAVING的时候不用GROUP BY不会报错,但没意义
SELECT MAX(salary) 
FROM employees
HAVING MAX(salary)>1000;

where不能过滤分组函数,过滤分组函数必须要用havingwhere必须紧跟from写

如果过滤条件中使用了聚合函数,则必须使用HAVING来替换WHERE。

SELECT department_id,MAX(salary) FROM employees
GROUP BY department_id 
HAVING MAX(salary)>10000;

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第5张图片

面试:你怎么理解“如果过滤条件使用到了组函数,则必须使用HAVING来替换WHERE”??

调优意识

1.过滤条件中有聚合函数时,则过滤条件必须声明在HAVING中

2.过滤条件中没有聚合函数时,则过滤条件声明在WHERE或HAVING中都可以。但是建议写在WHERE 中。WHERE的执行效率要高于HAVING

如下:方式1和方式2都能查询正确结果,但是我们推荐使用方式1

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第6张图片


四、LIMIT 分页

LIMIT -- 用于mysql分页,使用在SELECT语句最末尾。

第1个参数是,偏移量(即跳过多少行)

第2个参数是,显示的条目数

-- 语法格式:LIMIT 偏移量,条目数
SELECT * FROM `employees`
LIMIT 0,5;

LIMIT怎么用于分页呢?

假设前端请求的参数要求:每页显示pageSize条记录,显示第pageNo

limit用于分页,公式如下

-- (当前页数-1)*每页条数,每页条数
LIMIT (pageNo-1)*pageSize,pageSize;

即可显示,第pageNo页的pageSize条记录。

特殊情况:如果LIMIT后只有一个参数时

LIMIT 条目数;   等价于    LIMIT 0,条目数;

-- 语法格式:LIMIT 条目数
SELECT * FROM `employees`
LIMIT 5;

-- 语法格式:LIMIT 偏移量,条目数
SELECT * FROM `employees`
LIMIT 0,5;

MySQL8.0新特性:LIMIT 条目数 OFFSET 偏移量 

下面这2种写法是等效的,

-- LIMIT 偏移量,条目数
SELECT * FROM `employees`
LIMIT 1,2;

-- MySQL8.0新特性:LIMIT 条目数 OFFSET 偏移量 
SELECT * FROM `employees`
LIMIT 2 OFFSET 1;

 结果都是:

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第7张图片


五、MySQL8.0 窗口函数

MySQL从8.0版本开始支持窗口函数。窗口函数的作用类似于在查询中对数据进行分组;不同的是,分组操作会把分组的结果聚合成一条记录,而窗口函数是将结果置于每一条数据记录中

窗口函数介于单行函数和聚合函数之间 

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第8张图片

1、ROW_NUMBER()

需求:使用ROW_NUMBER()函数获取goods数据表中各类别的价格从高到低排序的各商品信息

Parttion by 用于给结果集进行分区

-- ROW_NUMBER() 无重复排名(相同排名的按序排名)
SELECT ROW_NUMBER() OVER(PARTITION BY category_id ORDER BY price DESC) AS row_num,
id,category_id,category,NAME,price,stock
FROM goods;

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第9张图片

结果解析:不同于GROUP BY,窗口函数并没有把分类id相同的捏成一行。只是把分类相同的行记录放在了一个分区内,并且同一个区内的行记录按照价格降序排列,OVER之后,给这波数据加个序号列,别名起为 row_num


2、RANK()

需求:使用RANK()函数获取goods数据表中各类别的价格从高到低排序的各商品信息

-- RANK() 有相同排名,但会跳过占用的排名
SELECT RANK() OVER(PARTITION BY category_id ORDER BY price DESC) AS row_num,
id,category_id,category,NAME,price,stock
FROM goods;

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第10张图片


3、DENSE_RANK()

需求:使用DENSE_RANK()函数获取goods数据表中各类别的价格从高到低排序的各商品信息

--  DENSE_RANK() 有相同排名,但不会跳过占用的排名
SELECT DENSE_RANK() OVER(PARTITION BY category_id ORDER BY price DESC) AS row_num,
id,category_id,category,NAME,price,stock
FROM goods;

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第11张图片


4、序号函数--常用示例

1、伪列给每一行加上行号

-- 每一行加上行号
SELECT row_number() over() rownum, department_id, last_name, salary
FROM employees

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第12张图片

2、PARTITION BY 按照工资分割、分组

--  PARTITION BY 按照工资分割、分组
SELECT row_number() over(PARTITION BY salary) rownum, department_id, last_name, salary
FROM employees

 2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第13张图片

 3、按照工资去重,比distinct好

-- 按照工资去重
SELECT *
FROM (
	SELECT row_number() over(PARTITION BY salary) rownum, department_id, last_name, salary
	FROM employees
) e
WHERE e.rownum = 1;

4. 按照部门分割,部门相同按照工资倒序排列

-- 按照部门分割,部门相同按照工资倒序排列
SELECT row_number() over(PARTITION BY department_id ORDER BY salary DESC) rownum, department_id, last_name, salary
FROM employees

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第14张图片

5.查询各个部门最高工资的几个人

SELECT last_name, salary,department_id
FROM (
       -- 按照部门分组,部门相同按照工资倒序排列
	SELECT row_number() over(PARTITION BY department_id ORDER BY salary DESC) rownum, department_id, last_name, salary
	FROM employees
) e
WHERE e.rownum = 1;

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第15张图片


六、子查询

子查询:嵌套在另一个SQL语句中的查询

SELECT语句可以嵌套在另一个SELECT中,UPDATE,DELETE,INSERT,CREATE语句等。

SELECT的SELECT中嵌套子查询

-- 在“t_employee”表中查询每个部门平均薪资和公司平均薪资的差值
SELECT did,AVG(salary),
AVG(salary)-(SELECT AVG(salary) FROM t_employee)
FROM t_employee
GROUP BY did;

SELECT的WHERE或HAVING中嵌套子查询

当子查询结果作为外层另一个SQL的过滤条件,通常把子查询嵌入到WHERE或HAVING中。

SELECT的FROM中嵌套子查询

当子查询结果是多列的结果时,通常将子查询放到FROM后面,然后采用给子查询结果取别名的方式,
把子查询结果当成一张“动态生成的临时表”使用

1、单行子查询   

where:在查询结果正筛选。

on必须配合join使用,且on后只写两张表的关联条件

当子查询的结果是单列单个值,那么可以直接使用比较运算符,如“<”、“<=”、“>”、“>=”、“=”、“!=”等与子查询结果进行比较。

问题引入:求谁的工资比Abel高?

-- 主查询(外查询)
SELECT *
FROM employees
WHERE salary > (
	-- 子查询(内查询)子查询在主查询之前执行完成
	SELECT salary
	FROM employees
	WHERE last_name = 'Abel'
);


-- 返回公司 工资最少 的员工的 last_name,job_id和salary
SELECT last_name, job_id, salary
FROM employees
WHERE salary = (
	SELECT MIN(salary)
	FROM employees
);

非法子查询

  1.  单行操作符只能用于操作单行子查询
  2. 子查询是空值,那么主查询也会是空值
-- 非法子查询报错
SELECT employee_id, last_name
FROM   employees
WHERE  salary =
                (SELECT   MIN(salary)
                 FROM     employees
                 GROUP BY department_id);


2、多行子查询

当子查询的结果是单列多个值,那么可以使用比较运算符IN或NOT IN进行比较。

当子查询的结果是单列多个值,还可以使用比较运算符, 如“<”、“<=”、“>”、“>=”、“=”、“!=”等搭配ANY、SOME、ALL等关键字与查询结果进行比较。

SELECT salary
FROM employees
WHERE job_id = 'IT_PROG'

这个sql的执行结果是:

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第16张图片

any 满足条件的任意一个  类似于”或“的关系 

-- 题目:返回其它部门中比 job_id为‘IT_PROG’部门 任一 工资低的员工的 员工号、姓名、job_id 以及salary
-- any : 满足条件的任意一个
SELECT employee_id, last_name, job_id, salary
FROM employees
WHERE salary < ANY(
	SELECT salary
	FROM employees
	WHERE job_id = 'IT_PROG'
) AND job_id <> 'IT_PROG';

all 满足所有的条件   类似于“与“ 的关系

-- 题目:返回其它部门中比job_id为‘IT_PROG’部门 所有 工资都低的员工的员工号、姓名、job_id 以及salary
-- all : 满足所有的条件
SELECT employee_id, last_name, job_id, salary
FROM employees
WHERE salary < ALL (
	SELECT salary
	FROM employees
	WHERE job_id = 'IT_PROG'
) AND job_id <> 'IT_PROG';

in 和 ”=any是一样的一样的

SELECT employee_id, last_name, job_id, salary
FROM employees
WHERE salary IN (
	SELECT salary
	FROM employees
	WHERE job_id = 'IT_PROG'
) AND job_id <> 'IT_PROG';

3、相关子查询

本,该,当前需要主查询多提供一个条件

相关子查询 3步走,
第一步,主查询把过滤条件给子查询【此部门】
第二步,子查询用where过滤,得到结果
第三步,子查询把过滤的结果返给主查询

-- 查询各部门中工资比 本 部门平均工资高的员工的员工号, 姓名和工资
SELECT employee_id, last_name, salary
FROM employees e1
WHERE salary > (
		SELECT AVG(salary)
		FROM employees e2
	   WHERE e2.department_id = e1.department_id  
)

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第17张图片


子查询还能这么玩??

-- sql是正确的
SELECT id,NAME,description,is_deleted,
(SELECT NAME FROM hse_dict WHERE id = hse_community.area_id) areaName,
(SELECT NAME FROM hse_dict WHERE id = hse_community.plate_id) plateName
FROM hse_community 

 上面的sql涉及到了另外一张表,字典表 hse_dict,运行结果是:

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第18张图片


七、SQL底层执行原理

1、SQL语句的编写顺序

#sg199语法:
SELECT ...,...,...(存在聚合函数)
FROM ...(LEFT/RIGHT) JOIN ... ON 多表的连接条件 
(LEFT/RIGHT) JOIN ... ON ....
WHERE 不包含聚合函数的过滤条件
GROUP BY ...,...
HAVING 包含聚合函数的过滤条件
ORDER BY ...,...(ASC/DESC)
LIMIT ...,...

2、SQL语句执行顺序

把整个select语句分为3块,按照下图标注的块顺序执行

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第19张图片


3、SQL语句执行过程

解释如下:

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第20张图片

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第21张图片


八、用户管理

MySQL数据库的安全性需要通过账户管理来保证。

1、登录MySQL服务器

最全的登录命令

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第22张图片


2、创建、删除、修改用户

mysql数据库下的user表

SELECT HOST,USER FROM mysql.user;

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第23张图片

创建用户

创建zhang3用户,默认host是%

CREATE USER 'zhang3' IDENTIFIED BY 'abc123'; 

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第24张图片

如果不想host是%,可以指定

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第25张图片

得出结论:mysql.user表的主键是host字段和user字段的联合主键

修改用户名

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第26张图片

修改后要记得 flush privileges

删除用户


3、设置当前用户密码

适用于root用户修改自己的密码,以及普通用户登录后修改自己的密码。

方式一:使用ALTER USER命令来修改当前用户密码

把当前用户的密码修改为abcabc

方式二:SET命令修改

该set语句会自动将密码加密后再赋值给当前用户 


4、修改其他用户的密码

root用户不仅可以修改自己的密码,还可以修改其他普通用户的密码。

方式一:使用ALTER语句修改普通用户的密码 

方式二:使用SET命令修改普通用户的密码


5、MySQL权限分布与授权原则

 查看MySQL有哪些权限

-- 查看权限列表
SHOW PRIVILEGES;

MySQL权限分布

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第27张图片

授予权限的原则

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第28张图片


6、授权命令

查看当前用户权限

SHOW GRANTS;

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第29张图片

给用户授权

'zhang3'@'%'用户授权

需要注意的是权限叠加

特殊授权操作

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第30张图片

此时,li4用户在权限层面来说和root的区别:不能给别人赋予权限


7、收回权限命令

MySQL中使用REVOKE语句取消用户的某些权限。

建议大家,尽量使用数据库自己的角色和用户机制来控制访问权限,不要轻易用Root账号。因为Root账号密码放在代码里面不安全,一旦泄露,数据库就会完全失去保护。而且,MySQL的权限控制功能十分完善,应该尽量利用,可以提高效率,而且安全可靠。


九、MySQL日志管理

1、MySQL日志

6类日志

2022/2/2 西安 mysql基础篇(04) ORDER BY、GROUP BY 、HAVING、LIMIT分页、窗口函数、子查询、SQL执行顺序_第31张图片

日志的弊端


2、慢查询日志

你可能感兴趣的:(笔记,mysql)