参考书籍:Mysql核心技术与最佳实践 /孔祥盛编著. -北京:人民邮电出版社,2014.5 ISBN 978-7-115-33769-6
一、select语句概述
语法形式:
select 字段列表 from 数据源 [where 条件表达式] [group by 分组字段|having 条件表达式] [order by 排序字段[asc|desc]]
1、select子句指定字段列表
- * 字段列表为数据源全部字段
- 表名.* 多表查询时,指定表的全部字段
- 字段列表 指定字段
注意:
- 可以使用as 关键字指定别名
- 多表查询时必须指定前缀。
特殊用法
select version(),now() as nowtime,pi(),1+2,null=null,null!=null,null is null;
:
2、使用谓词过滤记录
2.1使用 谓词distinct 过滤结果集中重复记录
select distinct department_name from classes;
2.2 使用谓词limit 查询某几行
select * from student limit 0,3 #limit [start,]length; #start表示从第几行检索,初始值为0 #length 表示需要检索的总数
3、使用from子句指定数据源
实际应用中,为了避免数据冗余,需要将一张大表划分为很多小表。检索是通常将小表组成大表。
在select中可以指定多个数据源,轻松实现从多张数据表中提取数据。
语法规则:
from 表名1 [连接类型] join 表名2 on 表1和标2连接条件
说明:SQL标准中,连接类型主要分为inner(内连接)和outer(外连接,又分left、right、full)
3.1 内连接(inner join)
内连接将两个表中满足指定连接条件的记录连接成新的结果集,并舍弃所有不满足连接的记录。内连接是默认的连接类型。
语法形式:
from 表1 [inner] join 表2 on 表1和表2之间的连接条件
例如:检索分配有班级的学生信息(内连接为默认类型)
select student_no,student_name,student.class_no,class_name,department_name from student join classes on student.class_no=classes.class_no;
3.2外连接(outer join)
外连接又分为左连接(left join)、右连接(right join)、完全连接(full join)
左连接或右连接时,只能过滤一张表,另外一张表不能能过滤。
完全连接时,所有结果都出现在结果集中。
3.2.1左连接语法
from 表1 left join 表2 on 表1 表2之间的连接条件
说明:结果集中包含表1的全部记录。若表中没有满足连接条件的记录,则结果集表2相应字段为NULL
例如:检索所有学生对于的班级信息
select student_no,student_name,student.class_no,class_name,department_name from student left join classes on student.class_no=classes.class_no;
3.2.2右连接
语法形式:
from 表1 l join 表2 on 表1 表2之间的连接条件
例如:检索所有班级的学生信息
select classes.class_no,student_no,student_name,student.class_no,class_name,department_name from student right join classes on student.class_no=classes.class_no;
总结:内连接、外连接区别在于内连接去除所有不符合连接条件的记录,外连接保留其中一个表所有记录。
4、多表链接
语法形式:
from 表1 [连接类型] join 表2 on 表1和表2之间的连接条件 [连接类型] join 表3 on 表2和表3之间的连接条件
例如:从student、score、choose表中查询学生成绩信息:
select student.student_no,student_name,course.course_no,course_name,score from student inner join choose on student.student_no=choose.student_no inner join course on choose.course_no=course.course_no;
二、使用where子句过滤
1、单一条件过滤集
常见表达式:= > >= < <= != !<(不小于) !>(不大于)
2、is NULL 运算符
判断是否为NULL,和is not NULL 相反。
select * from choose where score is NULL;
3、逻辑运算符
3.1 逻辑非!
select * from course where !(up_limit=60);
3.2and逻辑运算符
连接两个布尔表达式,当两个表达式都为true 时,整个逻辑表达式才为true
布尔表达式1 and 布尔表达式2
表达式 [not] between 起始值 and 终止值
比如成绩在70~90之间:
where score between 80 and 90
3.2 or 逻辑运算符
连接两个布尔表达式,两个都为false 时,整个逻辑表达式才为false
4、使用like模糊查找
like 运算符用于判断一个字符串是否与给定的模式相匹配。
模式是一种特殊的字符串,包含普通字符和通配符。
语法形式:
字符表达式 [not] like 模式
Mysql中常用通配符:
- % 匹配多个或多个字符组成的任意字符串
- _ 匹配任意一个字符
select * from student where student_name like '张_'; select * from student where student_name like '%三%';
三、使用order by 子句对结果集排序
语法格式:
order by 字段名 1 [asc|desc] [...,字段名 n [asc|desc]]
例如:成绩降序排序
select * from choose order by score desc;
四、聚合函数汇总结果集
1、count() 统计结果集中行数
select count(*) 学生人数 from student;
2、sum() 用于数值型字段累加求和
3、avg() 用于数值型字段求平均值
4、max() min() 最大值 最小值
五、group by 子句对记录分组统计
语法格式:
group by 字段列表[having 条件表达式] [with rollup]
单独使用group by子句对记录分组时,仅仅显示分组中某一条记录。因此单独使用group 子句分组实际意义不大,通常与聚合函数一起使用。
例如:
select * from student group by class_no;
1、group by 子句与聚合函数
例如:统计每个班学生人数
select class_name ,count(student_no) from classes left join student on student.class_no = classes.class_no group by classes.class_no;
例如:统计每个学生已经选了多少门课程、以及该生最高分、总分、平均成绩
select student.student_no,student_name,count(course_no),max(score),min(score),sum(score),avg(score) from student left join choose on student.student_no=choose.student_no group by student.student_no;
2、group by 子句与having 子句
having 子句用于设置分组或聚合函数的过滤筛选条件,通常与group by子句一起使用。
having 与where 格式相似,语法格式如下:
having 条件表达式
例如:检索平均成绩高于70分的学生及平均成绩(having 不能替换为where)
select choose.student_no,student_name,avg(score) from choose join student on choose.student_no=student.student_no group by student.student_no having avg (score)>70;
重要:对于包含where group by having 的语句执行顺序为:where=>group by=>having
3、group by 与 group_concat()
3.1 group_concat()可以把集合中字符串连接起来,如:
select group_concat('JAVA1','JAVA2','JAVA3');
3.2 group_concat还可以按照分组字段,将另一个字段的值使用逗号连接起来。
例如:统计所有班级的学生名单
select class_name ,group_concat(student_name) , concat(student_name) from classes left join student on student.class_no = classes.class_no group by classes.class_no;
4、group by 与with rollup 选项
如果分组后,需要在分组后加上一条汇总记录,这个任务可以通过with rollup选项实现。
例如:统计每个班学生人数,并在查询结果集最后一条记录附上所有班级的总人数。
select classes.class_no,count(student_no) from classes left join student on student.class_no=classes.class_no group by classes.class_no with rollup;
六、合并结果集
使用union 科技将多个select 语句查询结果集合成一个结果集,语法格式:
select 字段列表1 from table1 union [all] select 字段列表2 from table2 ...
说明:字段列表1与字段列表2字段个数必须相同,且具有相同数据类型。
union与union all 区别: union时,数据库会筛选掉重复记录,但是用union all时,Mysql会直接合并两个结果集,效率高于union。
例如:检索所有学生、教师信息
select student_no,student_name,student_contact from student union all select teacher_no ,teacher_name,teacher_contact from teacher;
七、子查询
定义:一个select语句能够返回单个值或者多个值,且该select语句嵌套在另一个SQL语句中。那么该Select语句称为‘子查询’,包含了子查询的SQL语句叫做‘主查询’。
- 通常将子查询写在小括号内
- 子查询一般用于主查询where having 子句中,与逻辑运算符一起构成where having 筛选条件。
1、子查询与比较运算符
如果子查询返回单个值,则可以将一个表达式的值与子查询结果集进行比较。
例如:
select class_name,student.student_no,student_name,course_name,score from classes join student on student.class_no = classes.class_no join choose on choose.student_no=student.student_no join course on choose.course_no = course.course_no where score > (select avg(score) from student ,choose where student.student_no = choose.student_no and student_name='张三');
2、子查询与in运算符
子查询金昌鱼in运算符一起使用,用于将一个表达式的值与子查询返回的一列值进行比较,如果表达式的值是此列值中任何一个值,则条件表达式为true,否则为false。
例如:检索2012 自动化1班所有学生成绩:
select student.student_no,student_name,course_name,score from course join choose on choose.course_no=course.course_no join student on choose.student_no=student.student_no where student.student_no in ( select student_no from student join classes on student.class_no=classes.class_no where classes.class_name='2012 自动化1班' );
3、子查询与exists逻辑运算符
exists 逻辑运算符用来检测子查询结果集中是否包含记录。如果结果集中恰好包含一条记录,则exists的结果为true,否则为false。在exists前面加上not 时,恰好相反。
例如:检索没有申请选修课的教师的信息:
select * from teacher where not exists( select *from course where course.teacher_no=teacher.teacher_no );
4、子查询与any运算符
any运算符通常与比较运算符一起使用。使用any运算符时,通过比较运算符将一个表达式的值与子查询返回的一列值逐一比较,若某次比较结果为true,则整个表达式为true,否则为false。
例如:检索‘2012 自动化2班’比‘2012 自动化1班’最低分高的学生信息。
select student.student_no,student_name,class_name from student join classes on student.class_no = classes.class_no join choose on choose.student_no=student.student_no where class_name='2012 自动化2班' and score> any( select score from choose join student on student.student_no = choose.student_no join classes on classes.class_no=student.class_no where class_name='2012 自动化1班' );
5、子查询与all运算符
all运算符通常与比较运算符一起使用。使用all运算符时,通过比较运算符将一个表达式的值与子查询返回的一列值逐一比较,若每次的比较结果都为true ,则整个表达式的值为true,否则为false。
例如:检索‘2012 自动化2班’比‘2012 自动化1班’最高分高的学生信息。
select student.student_no,student_name,class_name from student join classes on student.class_no = classes.class_no join choose on choose.student_no=student.student_no where class_name='2012 自动化2班' and score> all( select score from choose join student on student.student_no = choose.student_no join classes on classes.class_no=student.class_no where class_name='2012 自动化1班' );
九、正则表达式
语法结构:
字段名 [not] regexp [binary] '正则表达式'
select * from course where course_name regexp 'java';