在上一文章《【技术干货】作为测试,你必须知道的MySQL知识(一)》中我们已经学了MySQL基础知识。对于最常用、最重要的select语句将会在本文与大家分享,带你轻松搞定查询语句。
一、SQL查询语句逻辑执行顺序
学习select之前,需先知道查询语句逻辑执行顺序,了解了逻辑执行顺序,对我们写select语句有帮助,但是需要注意的是,逻辑顺序并不是真正执行的顺序,因为MySQL优化器会将SQL子句按最优的路径执行。如果想要查看实际执行顺序,可使用Explain关键字进行分析,获取对应的执行计划。
1、select语句格式
查询语句的使用都离不开以下的格式:
select distinct <select_list>
from <left_table><join_type> join <right_table>
on <join_condition>
where <where_condition>
group by <group_by_list>
having <having_condition>
order by <order_by_condition>
limit <limit_number>
需要记住,这是学好查询语句的基础~
2、逻辑执行顺序
以上select的逻辑执行顺序如下(前面的序号):
(7) select
(8) distinct <select_list>
(1) from <left_table>
(3) <join_type> join <right_table>
(2) on <join_condition>
(4) where <where_condition>
(5) group by <group_by_list>
(6) having <having_condition>
(9) order by <order_by_condition>
(10) limit <limit_number>
SQL逻辑执行顺序这是重点,面试常问,必须要掌握!!
二、常见运算符
查询语句中where后面支持多种运算符,进行条件的处理,其中常见运算符包括:比较运算、逻辑运算、模糊查询、范围查询、空判断。
1、常见比较运算
① 等于: =
② 大于: >
③ 大于等于: >=
④ 小于: <
⑤ 小于等于: <=
⑥ 不等于: != 或 <>
#例子1:查询体重大于110的用户
select * from t_user where weight>110;
#例子2:查询用户名称为aa的id及对应的name
select id,name from t_user where name ='aa';
2、常见逻辑运算
① and
② or
③ not
#例1:查询体重大于110且姓名为aa的用户:
select * from t_user where weight>110 and name = 'aa';
#例2:查询名称为bb或者是体重小于100的用户信息:
select * from t_user where name = 'bb' or weight<100;
#例3:查询体重不等于120的用户信息:
select * from t_user where not weight=120;
3、模糊查询
【模糊查询语法】:字段名 like <匹配字段字符串>
【常见的匹配字段字符串】:%、_、[] 、[^]
① %:0个或多个任意字符
#例1:查询姓孙的用户
select * from t_user where name like '孙%';
#例2:查询姓名含珍的用户
select * from t_user where name like '%珍%';
②_:1个任意字符
#查询姓孙且名字是一个字的用户
select * from t_user where name like '孙_';
③[]:在范围内的1个字符
#例1:表示字符范围A、B、C开头,后面任意字符
select * from book where name like [A-C]%;
#例2:表示书名以ABCN开头,后面任意字符
select * from book where name like [A-CN]%;
④[^]:不在范围内的1个字符
#表示字符范围不以ADN 开头,后面任意字符
select * from book where name like [^ADN]%;
4、常见范围查询
① in:表示在一个非连续的范围内
② between ... and ...:表示在一个连续的范围内
#例1:查询名字为'李先生'或'小李子'或'珍美丽'的用户信息
select * from t_user where name in ('李先生','小李子','珍美丽');
#例2:查询体重为100至130的用户
select * from t_user where weight between100 and 130;
5、常见空判断
① 判断为空:is null
② 判断非空:is not null
#例1:查询体重为空的用户信息
select * from t_user where weight is null;
#例2:查询体重不为空的用户信息
select * from t_user where weight is not null;
【注意】:null与''是不同的。
三、常见的查询类型
1、表连接(join)
使用JOIN 来联合多表查询,JOIN 按照功能大致分为如下三类:
① INNER JOIN(内连接):获取两个表中字段匹配关系的记录。
② LEFT JOIN(左连接):获取左表所有记录,即使右表没有对应匹配的记录。
③ RIGHT JOIN(右连接):与 LEFT JOIN 相反,用于获取右表所有记录,即使左表没有对应匹配的记录。
(1)INNER JOIN
select * from table1_name inner join table2_name on [依据什么条件连接]
->【举个栗子】:对表t_user与表t_order进行内连接
select * from t_user u inner join t_order o
on u.id=o.user_id;
(2)LEFT JOIN
select * from table1_name left join table2_name
on [依据什么条件连接]
->【举个栗子】:对表t_user与表t_order进行左连接
select * from t_user u left join t_order o
on u.id=o.user_id;
(3)RIGHT JOIN
select * from table1_name right join table2_name
on [依据什么条件连接]
->【举个栗子】:对表t_user与表t_order进行右连接
select * from t_user u right join t_order o
on u.id=o.user_id;
【内连接、左连接、右连接的区别】:
① 内连接:保留两表中交集的记录;
② 左连接:左表全部保留,右表关联不上用null表示;
③ 右连接:右表全部保留,左表关联不上的用null表示。
2、分组(group by)
group by语句是根据一个或多个列对结果集进行分组。在分组的列上我们经常会使用到聚合函数,因此,先了解常用的聚合函数:
① sum():求和
② avg():求平均数
③ count():统计记录条数
④ max():求最大值
⑤ min():求最小值
【group by语法】:
select column_name,function(column_name)
from table_name
where column_name operator value
group by column_name;
可以根据某个字段(column_name)进行分组。如果不指定分组字段,默认将所有记录作为一组。
->【举个栗子】:在emp表中,有3个字段,一个是员工id(id),一个是部门id(dept_id),一个是员工薪水(salary)
【问题1】:需要查询出每个部门的总薪水和平均薪水
select dept_id sum(salary) ,avg(salary)
from emp
group by dept_id;
【问题2】:统计满足条件的记录条数,统计出员工人数
select count(id) from emp;
select count(*) from emp;#包括空值在内的所有行
【问题3】:统计出每个部门薪水大于6000的员工人数
select dept_id count(id) from emp
where salary >6000
group by dept_id;
【问题4】:分组并排序。查询每个部门的平均薪水,并按照平均薪水的升序排序
#【写法1】:排序的字段不使用别名,直接用聚合函数AVG(salary)
select dept_id,AVG(salary) as avgsal
from emp
group by dept_id
order by AVG(salary) as c
#【写法2】:排序的字段使用别名avgsal
select dept_id,AVG(salary) as avgsal
from emp
group by dept_id
order by avgsal asc;
【注意】:
① 使用group by的select语句中的字段,应该出现在聚合函数中,或者出现在group by中;
② having子句可以使用聚合函数,而where子句不能使用。
③从逻辑执行过程可知:where是没有分组前对所有数据进行过滤,having是对分组后的数据进行过滤。
3 、子查询
子查询是指一个查询语句嵌套在另一个查询语句内部的查询。
① 在条件中使用子查询
->【举个栗子】:一张user表,有2个字段,一个是名称(name),一个是年龄(age),查询出比小李年龄高的人有哪些?
select * from `user`
where age>(select age from `user` where name="小李");
②在from语句中使用子查询
->【举个栗子】:获取员工工资低于所在部门的平均工资的员工信息
select e.empno,e.ename,e.sal,e.deptno
from emp e left join
(select deptno,avg(sal) dept_avg_sal from emp group by deptno) dept_avg
on dept_avg.deptno=e.deptno
where e.sal< dept_avg.avgsal;
4、排序(order by)
① 降序(desc):
要对某个字段进行降序,可以在查询语句后可使用:order by <排序的字段名> desc
select * from t_user order by weight desc; //根据weight降序
② 升序(asc):
要对某个字段进行升序,可以在查询语句后可使用:order by <排序的字段名> asc
select * from t_user order by id asc; //根据id升序
【注意】:order by默认情况下是升序,asc可省略不写。
③ 结合使用:
有2个维度的排序时,使用逗号隔开2个排序,优先使用前者进行排序,再使用后者进行排序。
select * from t_user order by weight desc,id asc; //根据weight降序,如果存在相同weight,根据id升序
5、分页(limit)
limit:限制查询数据条数,经常在分页的场景中应用。LIMIT子句接受一个或两个参数。参数值都必须为零或正整数。limit的使用格式:
select * from
[where Clause]
[limit N][offset M]
【参数解释】:
limit N : 返回 N 条记录;
offset M : 跳过 M 条记录, 默认 M=0;
limit N,M : 从第 N 条记录开始, 返回 M 条记录。
->【举个栗子】:
#检索记录1行数据
select * from t_user limit1;
#检索6-15行记录
select * from t_user limit 5,10;
【注意】:limit的两个参数中:
① 第1个参数:指要返回的第一行的偏移量。第一行的偏移量为0,而不是1;
② 第2个参数:指要返回的记录行数。
如上面"检索6-15行记录"例子中,第1个参数为5,其实指的是第6行;第2个参数为10,指的是从第6行开始,取10条记录,所以是获取到6-15的记录。
6、去重(distinct、group by)
① distinct
当需要查询出某个字段不重复的记录时,可以使用distinct来过滤重复的记录,格式如下:
select distinct expression[,expression...]
from tables
[where conditions];
使用distinct可以进行单字段去重、多字段去重、所有字段去重、以及与聚合函数的综合使用。
-->【举个栗子】:student表中有name、age、weight3个字段字段。
#【单字段去重】:根据age进行去重
select distinct age from student;
#【多字段去重】:根据name、age组合确定结果集的唯一性
select distinct name,age from student;
#【所有字段】:根据name、age、weight所有字段组合确定结果集的唯一性
select distinct * from student
#【DISTINCT和聚合函数综合应用】:
# ① 查询student表中对name、age字段去重之后记录的条数
select count(distinctname,age) from student;
# ② 查询student表中对name、age字段组合后重复的记录条数
select count(*) as repetitions,name, age
from student
group by name,age
having repetitions >1;
② group by
使用distinct之后,只能返回去重的字段,而不能返回其他的字段,可以使用group by进行去重查询,
select name, age
from student
group by(name, age);
【注意】:
① distinct只能在select语句中使用;
② distinct必须在所有字段的最前面;
③ 多个字段去重时,多个字段组合后一样时才会被去重;
④ 列中有null值,当对该列使用distinct子句,将保留一个null值(所有null值被视为相同的值)。