玲珑骰(tou)子安红豆,入骨相思知不知?
骰子(tóu zi),又称色子(shǎi zi)
使用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`;
3、 二级排序,如果第 1 个字段相等,则按第 2 个字段排序,依次类推。
在对多列进行排序的时候,首先排序的第一列必须有相同的列值,才会对第二列进行排序。如果第一列数据中所有值都是唯一的,将不再对第二列进行排序。
#按照工资降序排列,工资相同则按照姓名升序排列 SELECT `last_name`,`salary` FROM `employees` ORDER BY `salary` DESC, `last_name` ASC;
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的执行流程有关。。在本篇文章最后有
分组允许把数据分为多个逻辑组,以便能对每个组进行聚集计算。
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;
HAVING的使用是依托于GROUP BY
#在使用HAVING的时候不用GROUP BY不会报错,但没意义
SELECT MAX(salary)
FROM employees
HAVING MAX(salary)>1000;
where不能过滤分组函数,过滤分组函数必须要用having,where必须紧跟from写
如果过滤条件中使用了聚合函数,则必须使用HAVING来替换WHERE。
SELECT department_id,MAX(salary) FROM employees
GROUP BY department_id
HAVING MAX(salary)>10000;
面试:你怎么理解“如果过滤条件使用到了组函数,则必须使用HAVING来替换WHERE”??
调优意识
1.过滤条件中有聚合函数时,则过滤条件必须声明在HAVING中
2.过滤条件中没有聚合函数时,则过滤条件声明在WHERE或HAVING中都可以。但是建议写在WHERE 中。WHERE的执行效率要高于HAVING。
如下:方式1和方式2都能查询正确结果,但是我们推荐使用方式1
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;
结果都是:
MySQL从8.0版本开始支持窗口函数。窗口函数的作用类似于在查询中对数据进行分组;不同的是,分组操作会把分组的结果聚合成一条记录,而窗口函数是将结果置于每一条数据记录中。
窗口函数介于单行函数和聚合函数之间
需求:使用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;
结果解析:不同于GROUP BY,窗口函数并没有把分类id相同的捏成一行。只是把分类相同的行记录放在了一个分区内,并且同一个区内的行记录按照价格降序排列,OVER之后,给这波数据加个序号列,别名起为 row_num
需求:使用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;
需求:使用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;
1、伪列给每一行加上行号
-- 每一行加上行号
SELECT row_number() over() rownum, department_id, last_name, salary
FROM employees
2、PARTITION BY 按照工资分割、分组
-- PARTITION BY 按照工资分割、分组
SELECT row_number() over(PARTITION BY salary) rownum, department_id, last_name, salary
FROM employees
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
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;
子查询:嵌套在另一个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后面,然后采用给子查询结果取别名的方式, 把子查询结果当成一张“动态生成的临时表”使用
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 );
非法子查询
- 单行操作符只能用于操作单行子查询
- 子查询是空值,那么主查询也会是空值
-- 非法子查询报错
SELECT employee_id, last_name
FROM employees
WHERE salary =
(SELECT MIN(salary)
FROM employees
GROUP BY department_id);
当子查询的结果是单列多个值,那么可以使用比较运算符IN或NOT IN进行比较。
当子查询的结果是单列多个值,还可以使用比较运算符, 如“<”、“<=”、“>”、“>=”、“=”、“!=”等搭配ANY、SOME、ALL等关键字与查询结果进行比较。
SELECT salary FROM employees WHERE job_id = 'IT_PROG'
这个sql的执行结果是:
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步走,
第一步,主查询把过滤条件给子查询【此部门】
第二步,子查询用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
)
子查询还能这么玩??
-- 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,运行结果是:
#sg199语法:
SELECT ...,...,...(存在聚合函数)
FROM ...(LEFT/RIGHT) JOIN ... ON 多表的连接条件
(LEFT/RIGHT) JOIN ... ON ....
WHERE 不包含聚合函数的过滤条件
GROUP BY ...,...
HAVING 包含聚合函数的过滤条件
ORDER BY ...,...(ASC/DESC)
LIMIT ...,...
把整个select语句分为3块,按照下图标注的块顺序执行
解释如下:
MySQL数据库的安全性需要通过账户管理来保证。
最全的登录命令
mysql数据库下的user表
SELECT HOST,USER FROM mysql.user;
创建用户
创建zhang3用户,默认host是%
CREATE USER 'zhang3' IDENTIFIED BY 'abc123';
如果不想host是%,可以指定
得出结论:mysql.user表的主键是host字段和user字段的联合主键
修改用户名
修改后要记得 flush privileges
删除用户
适用于root用户修改自己的密码,以及普通用户登录后修改自己的密码。
方式一:使用ALTER USER命令来修改当前用户密码
把当前用户的密码修改为abcabc
方式二:SET命令修改
该set语句会自动将密码加密后再赋值给当前用户
root用户不仅可以修改自己的密码,还可以修改其他普通用户的密码。
方式一:使用ALTER语句修改普通用户的密码
方式二:使用SET命令修改普通用户的密码
查看MySQL有哪些权限
-- 查看权限列表
SHOW PRIVILEGES;
MySQL权限分布
授予权限的原则
查看当前用户权限
SHOW GRANTS;
给用户授权
对'zhang3'@'%'用户授权
需要注意的是权限叠加
特殊授权操作
此时,li4用户在权限层面来说和root的区别:不能给别人赋予权限
MySQL中使用REVOKE语句取消用户的某些权限。
建议大家,尽量使用数据库自己的角色和用户机制来控制访问权限,不要轻易用Root账号。因为Root账号密码放在代码里面不安全,一旦泄露,数据库就会完全失去保护。而且,MySQL的权限控制功能十分完善,应该尽量利用,可以提高效率,而且安全可靠。
6类日志
日志的弊端