第三章 模糊查询与分组查询 ① 笔记
1. 内容回顾
1.1. 课前测试
1.2. 上节内容
2. 本章重点
2.1. 增删改
2.2. 级联操作
2.3. 查询
2.4. 函数
3. 具体内容
3.1. 增删改语句
3.1.1 insert 语句
语法:
INSERT [INTO] table_name [(COLUMN1 [,COLUMN2 [,......]])]
VALUES (VALUE1 [,VALUE2 [,......]);
省略列名:前提是按顺序插入所有列,值和列要一一对应
一次录入多行数据
INSERT [INTO] table_name [(COLUMN1 [,COLUMN2 [,......]])]
VALUES
(VALUE1 [,VALUE2 [,......]),
(VALUE1 [,VALUE2 [,......]),
(VALUE1 [,VALUE2 [,......]);
#在innodb存储引擎下,会到自增断层
INSERT [INTO] table_name [(COLUMN1 [,COLUMN2 [,......]])]
select VALUE1,VALUE1,[,......] union
select VALUE1,VALUE1,[,......]
3.1.2 update 语句
UPDATE table_name SET
COLUMN1={}, COLUMN2={}......
WHERE<表达式>
3.1.3 delete 删除语句
DELETE FROM table_name WHERE <表达式>
删除表中的数据:
delete: 根据条件删除,逐行删除。自增值不会重置。
truncate:整表删除,无法设定条件,效率高,自增列会重新计数,无法恢复数据;无法直接删
除有外键引用的表。
#删除数据
#以数据行为单位进行逐行删除,删除速度较慢
# 安全,可以记录日志,需要的时候可以通过日志进行恢复
delete from 表 [where 条件]
#truncate 截断 、截取
# 直接删除整张表中的数据,相当于先把物理表删了,然后又创建了一个新表
# 执行效率高,但是无法设定条件
# 自增列会重新计数
truncate table 表名;
3.1.4 级联
涉及到有主外键关联的数据表:
1、删除数据时:需要先删外键表,再删主键表
2、更新数据时:
3、录入数据时:先录入主键,再录入外键
级联:当更新(删除)主键表中的数据时,外键表中引用的数据会自动更新(删除)
cascade:删除主键时自动删除外键表中引用的数据,修改时自动更新外键表中引用的数据
# on delete CASCADE :开启 删除 级联
# on update CASCADE : 开启 更新 级联
alter table emp
add CONSTRAINT fk_deptno FOREIGN key (deptno)
REFERENCES dept(deptno)
on delete CASCADE on update CASCADE; #添加级联设置
3.2 查询
语法:
select 列名1,列名2 # 查询列
from 表名 # 从 某张表中
#可选
where 条件表达式
group by 列名
having 条件表达式
order by 列名
limit ?,? 分页
说明:
我们想查询该表的那些列 可以直接写列名 ,顺序可以自定义
SELECT `name`,age,address,sex from student;
可以使用 select * 查询所有列。 *号代表所有列。但是这种查询效率低。
SELECT * from student;
列和表都可以起别名
SELECT s.`name`,s.age+3 a,s.address from student s;
查询中列支持运算
SELECT s.`name`,s.age+3 a,s.address from student s;
实例
#查询测试
#查询列
#1.指定列名查询
select id,name,sex from student
#2.查询所有
select * from student;
#3.通过表设置别名,指定列查询
select s.id,s.name,s.sex,s.* from student s
#4.查询常量列,并设置常量列的列名
select id,
name,
sex,
'仁和路小学' school,
'少先队员' as 身份
from student
#为列起别名: 1.列加空格后面写别名 2.as语法起别名
select id 学号,name 姓名,sex as 性别 from student
#针对列做运算
select id+10000 新学号,name 姓名 from student
3.2.1 去重查询
去除查询结果中的重复数据
select distinct 列名 from 表名;
3.2.2 条件查询where语句
SQL语句中的条件表达式:查询条件、判断条件、修改条件
条件运算符:= > < >= <= 不等:<> 和 !=
算术运算符:+ – * / %(mod) 不支持:++ – 复合赋值 += -=
逻辑运算符:and(&&) , not(!) , or(||)
多条件查询
#带条件查询
#条件表达式:
#关系运算符: >,>=,<,<=,=,!=,<>
#逻辑运算符: and(&&),or(||),not(!)
#查询价格大于5元的商品
SELECT # 1. 什么操作
goodsId,goodsName,price # 4. 查询什么数据
from goods # 2. 针对那个表
where price>5 # 3. 条件
#查询价格大于10元的并且产地是广州的商品
SELECT #1.什么操作
* #4.查什么结果
from goods #2.针对哪个表
where price>10 and address = '广州' #3.条件
#where price > 10 && address ='广州'
#查询商品类型是食品,或者价格小于5元的商品
SELECT
*
from goods
where categoryId = 1 or price<5
#查询价格不小于5的商品
SELECT
*
from goods
where not price < 5
#查询产地不是广州的
select
*
from goods
where not address = '广州'
#where address <> '广州'
#where address != '广州'
#带条件修改
#1. 将产地是郑州的并且是食品的商品都上涨1元钱,并且生产日期改为当前日期
update goods # 1.修改哪个表
set price = price+1, #3.修改哪些列
produceDate = now()
where address = '郑州' and categoryId = 1 # 2.修改哪些记录
select * from goods where address = '郑州' and categoryId = 1
#2. 将价格小于5的并且是饮品的商品产地改为新乡
update goods
set address = '新乡'
where price<5 and categoryId = 2
select * from goods where price<5 and categoryId = 2
#带条件删除
#1. 删除生产日期小于2005-01-01的商品
delete from goods #1.删除哪个表的数据
where produceDate< '2005-01-01' #2.删除哪些记录
select * from goods where produceDate< '2005-01-01'
范围查询: between and
#3.多条件查询,使用between AND(查询某个连续期间的序列数据)
#查询商品编号是2-9之间的数据
SELECT
*
from goods
where goodsId between 2 and 9 #包含开始和结束
#where goodsId>=2 and goodsId<=9
#查询生产日期在2010-01-01 和2022-01-01之间的商品
范围查询: in 的使用
#4.多条件查询,使用in(也是范围条件查询,可以用于不连续的条件)
#查询商品是面包和鸡蛋的记录
SELECT
*
from goods
where goodsName in ('面包','鸡蛋')
#where goodsName = '面包' or goodsName = '鸡蛋'
#查询商品编号是1,3,5的商品
#查询产地是广州和郑州的商品
3.2.3 模糊查询
3.2.3.1 正则通配符
正则模式REGEXP操作符
“.” 匹配任意单个的字符。
“[ ]” 匹配在[]内的任意一个字符
[^] 匹配不在[]内的任意一个字符
“ * ” 匹配零个或多个在它前面的字符
“+” 匹配+前面的字符1次或多次
“{n}” 匹配前面的字符至少n次
“^” 匹配文本的开始字符
“$” 匹配文本的结尾字符
//匹配名字以a开头 c结尾的名字
select * from student where `name` REGEXP'^a.c$';
3.2.3.2 模糊查询like
与’%‘结合使用:匹配任意长度任意内容
与’_’结合使用:匹配一个长度任意内容
'%a' //以a结尾的数据
'a%' //以a开头的数据
'%a%' //含有a的数据,三位且中间字母是a的
'_a' //两位且结尾字母是a的
'a_' //两位且开头字母是a的
%:表示任意 0 个或多个字符。可匹配任意类型和长度的字符,有些情况下若是中文,请使用两
个百分号(%%)表示。
_:表示任意单个字符。匹配单个任意字符,它常用来限制表达式的字符长度语句。
实例
#模糊查询
#1. like + % : 其中%匹配任意长度任意内容
#2. like + _ : 其中_匹配一个长度任意内容
#3. REGEXP : 正则表达式匹配
# \d,\s,\w,[],[^],+,*,?,{n,m},^,$
#商品名字有面的商品
select
*
from goods
where goodsName like '%面%'
#查询以面开始的记录
SELECT
*
from goods
where goodsName like '面%'
#查询以面开始的两个字的内容
SELECT
*
from goods
where goodsName like '面_' #限定两个字
#where goodsName like '面%' #两个字三个字都出来了,不对
#用正则表达式查询,以面开头的记录
select
*
from goods
where goodsName REGEXP '^面' #以面开始
3.2.4 排序操作
order by 列名 asc 默认升序 desc 降序, 列名 升序,降序…
#排序:将查询结果按照某个列的特定次序(升序 asc,降序 desc)呈现
select
*
from goods
order by goodsId desc #按照商品编号降序呈现
#查询商品,按价格从小到达排序
SELECT
*
from goods
order by price asc # asc升序
#多字段排序:按照价格升序,如果价格相同,生产日期降序排序
SELECT
*
from goods
order by price,produceDate desc
#先按第一个列排序,第一列相等的情况下在第二列排序
SELECT
*
from goods
order by goodsId asc ,price desc
#因为goodsId不会重复,所以没有必要按价格排序
3.2.5 分页查询limit(要和排序结合使用)
每次我们直接 select * from t_people 会将数据全部查询出来,如果一张表数据量比较大 ,此时 容易爆炸,所以真正开发的时候,都是只查一部分数据,所以都是进行分页操作的。
#分页查询: limit 起始位置,记录个数
# 意思:从起始位置之后,返回指定记录个数
select * from goods;
#查询前三条记录
SELECT
*
from goods
limit 3 #起始位置0可以省略
#limit 0,3 #从0之后取3条,不包含0
#获取4,5,6数据
SELECT
*
from goods
limit 3,3 #从3开始,取3条,不包含开始位置
#分页:设定每页5条记录,现有12条记录,问分为几页?
# 第一页: 1-5 第二页:6-10 第三页:11-12
#每页5条件,问查询第3页的数据,应该怎么写
SELECT
*
from goods
limit 10,5 # 开始位置=(页数-1)*每页记录数
#分页必须和排序一起使用
#按照价格升序排序进行分页
select * from goods
order by price asc
limit 10,5
3.2.6 聚合函数(汇总函数)和分组查询
3.2.6.1.聚合函数(汇总函数)
就是对某一列的数据进行运算获取某些列的最大值、最小值、平均值等统计分析信
息,有时候还需要计算出究竟查询到多少行数据项。分别有:sum(列),count(注意非空
值) 计数、max(列)、min(列)、avg(列),count(空值)不计入数据。
count(列名/*) 如果列名存在null值,不计入总数。
#汇总函数(聚合函数):针对多条数据计算出一个结果
# count(*/列名): 统计记录数,统计非空值,统计唯一值
# max(列名): 查询某列中的最大值
# min(列名): 查询某列中的最小值
# sum(列名): 针对列所有值求和
# avg(列名): 针对列所有值求平均
# 聚合函数可以单独使用,也可以与分组一起使用(重点)
#汇总函数(聚合函数)
#count(*/列名): 统计记录个数,注意null不被统计
#统计学生表有几条记录
select * from studentInfo;
select count(*) from studentInfo
select count(studentId) from studentInfo;
#null值不会被统计
select count(province) from studentInfo;
#去重计数 count (distinct 列)
select count(DISTINCT province) from studentInfo;
/*
update studentinfo
set province = null
where studentId = 5
*/
#sum(列):求和 avg(列):请平均
#统计张三同学的成绩之和
select * from examInfo;
SELECT
sum(score) as '总分',
avg(score) as '平均分',
count(*) as '考试数量'
from examinfo
where studentId = 1
#max(列):求最大 min(列):求最小
#求张三三门成绩中的最高分和最低分
select
max(score) as 最高分,min(score) 最低分
from examinfo
where studentId= 1
3.2.6.2.分组查询
group by 列名 是将 某一列 相同数据的行当成一组
-- 分组查询
-- 求出每个班级的人数 按照班级分组
SELECT
classId, #分组字段
count(*) as 人数, #分组汇总
from studentinfo
group by classId
-- 求每个班级的男生和女生人数(多字段分组)
SELECT
classId,sex,count(*) as 人数
from studentinfo
group by classId,sex
order by classId,sex desc
having 对分组后的数据做过滤,注意分组查询添加条件 group by 列名 having 条件;
where 用在分组之前的条件过滤
-- 查询出所有男生人数大于2的班级
SELECT
classId,sex,count(*)
from studentinfo
group by classId,sex
having count(*)>=2 and sex='男' #having 分组之后条件过滤
#第二种写法??
SELECT
classId,count(*) #每个班级的男生
from studentinfo
where sex = '男' #先查询男生
group by classId #再按班级分组
having count(*)>=2
3.2.6.3.行转列
#行转列
#1.查询中可以包含常量列
select
*, '中国' as 出产国
, 'aaa' as 列名1
from goods
#2. case when then else end 语法(分支 switch case)
select * from exam
SELECT
stuName,
courseName,
score,
case when score>=90 then '优秀'
when score>=80 then '良好'
when score>=60 then '中等'
else '差'
end
as 等级
from exam
#实现行专列
#1.扩展常量列
select * from exam
SELECT
stuName,
case when courseName='语文' then score end as 语文,
case when courseName='数学' then score end as 数学,
case when courseName='英语' then score end as 英语
from exam
#2.分组汇总
SELECT
stuName,
max(case when courseName='语文' then score end) as 语文,
max(case when courseName='数学' then score end) as 数学,
max(case when courseName='英语' then score end) as 英语
from exam
group by stuName
3.2.6.4.小结
select 列名
from 表名
where 条件
group by 分组列名
having 过滤条件
order by 排序列名
limit start,length; #分页查询某几条
3.3 多表查询(重难点)
3.3.1 为什么要多表联查
数据来源多张表的时候需要进⾏关联查询 。在实际开发过程中很多时候需要同时使⽤多
个表中的数据
多表关联前提: 表之间有对应的数据列或外键约束。
3.3.2 内连接(等值连接:where,[inner] join)
内连接和外连接一样都是最常用的连接查询,它根据表中共同的列进行匹配,特别
是两个表存在主外键关系时,通常会使用到内连接查询 内连接也称为等值连接,返回
的结果集是两个表中所有相匹配的数据,舍弃不匹配的数据。
1)where等值连接(隐式内连接):简单,但是碰到问题不好调。
select 列名......
from 表1,表2,表3,表4....
where 关联条件、还可以过滤条件
#多表查询:查询学生姓名,性别,班级名称
#内连接(等值连接): 1.where连接 2.inner join 连接
#内连接的特点:多表之间能完全匹配的数据才会查询出来
#1.where连接查多表数据
SELECT
#*
s.name,s.sex,c.className
from studentInfo s , classInfo c #从两个表查询
where s.classId = c.classId #两个表的关联条件
#查询成绩信息: 显示学生姓名,课程名称,分数
select * from examInfo;
SELECT
#*
s.name,c.courseName,e.score
from examInfo e, studentInfo s, courseInfo c
where e.studentId = s.studentId
and e.courseId = c.courseId
order by s.name
2)inner join内连接(显式内连接)on ,扩展方便
select 列名,......
from 表1
[inner] join 表2 on 关联条件
[inner] join 表3 on 关联条件
[inner] join 表4 on 关联条件
where 过滤条件;
练习:
#inner join 连接
#两表关联之后合并成一张大表,再与其他表合并
#查询:学生姓名,性别,班级名称
SELECT
s.name,s.sex,c.className
from studentInfo s #第一个表
inner join classInfo c #连接第二个表
on s.classId = c.classId #以什么条件连接
#查询:学生姓名,课程名字,分数
SELECT
s.name,c.courseName,e.score
from examinfo e
inner join courseInfo c
on e.courseId = c.courseId
inner join studentInfo s
on e.studentId = s.studentId
order by s.name
注意:内连接时,如果表中的数据找不到另外一个表的对应记录,则数据不会被查询出来
#内连接的特点:多表之间能完全匹配的数据才会查询出来
#问题:对于内连接,如果两表中的数据没有对应关联,是否会查询出来
insert into classinfo
(className)
VALUES
('AAA03');
insert into studentInfo
(name,sex,birthday,province,classId)
values
('郭靖','男','2002-01-01','湖北',null),
('黄蓉','男','2002-01-01','湖北',NULL);
select * from classInfo;
select * from studentInfo;
#内连接(等值连接):where ,inner JOIN
select
*
from studentInfo s , classInfo c
where s.classId = c.classId;
SELECT
s.name,s.sex,c.className
from studentInfo s #第一个表
inner join classInfo c #连接第二个表
on s.classId = c.classId; #以什么条件连接
3.3.3 外连接
外连接是至少返回一个表中的所有记录,根据匹配条件有选择性地返回另一张表的
记录 外连接就是在满足表连接关系的情况下不但可以查找出匹配的数据,而且还可以
包含左表,右表或是两表中的所有的数据行
左外连接
左外保证左表完整、如果不匹配null值填充
SELECT * from 表1 LEFT JOIN 表2 ON 关联条件;
实例
#外连接: 对有对应列或外键约束的表进行关联查询
# 一个表的数据会全部显示(不管另外一个表是否有对应记录)
# 另外一个表来匹配第一个表,对应上的显示,对应不上不显示
#左外连接: left [outer] join
#以左表为主,左表数据全部显示,
#右表数据匹配左表,匹配上的显示,匹配不上的不显示,用null替代
#查询所有班级的学生情况
#要求所有班级都要显示出来
SELECT
*
from classInfo c # 写在前面的表称为左表
left join studentInfo s #写在后面的称为右表
on c.classId = s.classId
#查询所有学生的信息,和对应班级
select
*
from studentInfo s
left outer join classInfo c
on s.classId = c.classId
右外连接
右外保证右表完整、如果不匹配null值填充
SELECT * from 表1 right JOIN 表2 ON 条件;
#右外连接: right [outer] join
#以右表为主,右表数据全部显示,
#左表数据匹配右表,匹配上的显示,匹配不上的不显示,用null替代
select
*
from classInfo c #左表
right join studentInfo s #右表
on c.classId = s.classId
SELECT
*
from studentInfo s #左表
right join classInfo c #右表
on s.classId = c.classId
#查询所有的学生成绩:学生姓名,课程名字,分数
SELECT
s.name,c.courseName,e.score
from studentInfo s
left join examInfo e
on s.studentId = e.studentId
left join courseInfo c
on e.courseId = c.courseId
#查询没有参加考试的学生信息
SELECT
s.name,c.courseName,e.score
from studentInfo s
left join examInfo e
on s.studentId = e.studentId
left join courseInfo c
on e.courseId = c.courseId
where e.score <=> null #空值相等判断
#where e.score is null
#where e.score = null #null值不能用 = 判断
3.3.4 交叉连接 cross join
交叉联接返回左表中的所有行,左表中的每一行与右表中的所有行再一一组合,相
当于两个表“相乘”左表中每一行的数据都和右表组合一次,相当于两表的排列组合,返
回的条数其实就是两表的成绩交叉连接没有关联条件
#交叉连接(笛卡尔积): 两表相乘,没有关联条件
select
*
from studentInfo s
cross join classInfo c
#一般在考勤业务中使用
#生成一个学生的31天记录
3.3.5 自关联
#自关联(树形菜单,员工(上下级关系))
#西游取经团(公司人事结构:职员,领导)
create table xyj
(
id int primary key, #人员编号
name varchar(20), #人员姓名
pid int #上级领导编号
);
select * from xyj;
insert into xyj
(id,name,pid)
VALUES
(1,'如来',null),
(2,'菩萨',1),
(3,'唐僧',2),
(4,'孙悟空',3),
(5,'猪八戒',3),
(6,'沙和尚',3);
#请查询,所有员工信息,以及员工的领导
# 如来 NULL
# 菩萨 如来
# 唐僧 菩萨
# 孙悟空 唐增
#查询每个员工的领导
SELECT
a.name,b.name
from xyj a #员工
left join xyj b #领导表
on a.pid = b.id
#子查询
select
name,(select name from xyj where id = a.pid)
from xyj a
#查询每个领导下的小兵
SELECT
a.name,b.name
from xyj a #领导表
join xyj b #员工表
on a.id = b.pid
3.4 MySQL函数
MySQL 函数https://www.runoob.com/mysql/mysql-functions.html
#mysql函数
#请查询出如下结果
#张三(男)
#李四(女)
select name,sex from studentInfo
#mysql加法只能做数学运算
select name+'('+sex+')' from studentInfo
#字符串拼接
select concat('a','b','c')
select concat(name,'(',sex,')') as 姓名 from studentInfo;
#名字是三个字: char_LENGTH(字符串) 字符串长度
select * from studentinfo
where char_LENGTH(name) = 3
#当前日期
select now()
select *,now() as 入学日期 from studentInfo
select *,'2020-01-01' as 入学日期 from studentInfo
#2000年出生的学生
select * from studentInfo
where year(birthday)=2002
4. 本章总结
带条件增删改
查询
多条件查询
模糊查询
排序
聚合函数和分组查询
多表查询×××××重点中的重点
5. 课后作业
题目2:
MySQL查询语句练习题45题版https://blog.csdn.net/weixin_39718665/article/details/78161013
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/118112.html