1.去重查询
根据之前创建的数据库表和数据,我们提一个需求,查询所有参加了考试的学生的学号
select `studentno` from `result` --查询所有有成绩的学生的学号
根据结果,可以看出,数据有大量的重复,因此我们可以使用distinct
对数据进行去重查询。
SELECT DISTINCT `studentno` from `result`;
对比两者的查询,显然这种去重的方式更加适用,重复的数据只显示一条
。
2.where条件子句
作用:检索数据中符合条件
的值
逻辑运算符
运算符 | 语法 | 描述 |
---|---|---|
and ,&& | a and b,a && b | 逻辑与 |
or ,|| | a or b,a || b | 逻辑或 |
not ,! | not a,! b | 逻辑非 |
3.模糊查询
运算符 | 语法 | 描述 |
---|---|---|
is null | a is null | 如果a为null,返回true |
is not null | a is not null | 如果a不为null,返回true |
between…and… | a between b and c | 若a在b、c之间,返回true |
Like | a like b | SQL匹配,如果a匹配b,返回true |
in | a in (a1,a2,a3,a4…) | 如果a在 (a1,a2,a3…) 中的某一个,则返回true |
模糊查询举例:
-
like
相关操作(能够进行模糊匹配)
#查询名字是刘开头的(姓刘的)
select * from `student` where `studentname` like "刘%" --%(代表0到任意个字符)
#查询姓刘的同学,姓名只有两个字的
select * from `student` where `studentname` like "刘_" --_(代表一个字符)
#查询姓刘的同学,姓名为三个字的
select * from `student` where `studentname` like "刘__"
#查询姓名中带有"家"字的同学
select * from `student` where `studentname` like "%家%"
-
in
相关操作(in只能具体匹配)
#查询1001,1002,1003号学生
select * from `student` where `studentno` in (1001,1002,1003)
#查询在安徽、北京的学生
select * from `student` where `address` in ('安徽','北京')
-
null、not null
相关操作
#查询地址为空的学生,空可能是""或者null
select * from `student` where `address` = '' or `address` is null
#查询有出生日期的学生,即出生日期不为空
select * from `student` where `borndate` is not null
4.联表查询
我们在做查询的时候,会遇到可能一张表满足不了我们要求的情况,可能要求获取的数据来自于两张、三张甚至更多张表,对此,我们就应该使用联表查询。
举个例子:
根据之前我们新建的数据库和表,我们提一个需求,获取参加了考试的学生的信息,包括学生的姓名,学号,学生考试的科目的编号,分数
select * from `student`
select * from `result`
这样查询出来的效果,我们还需要一个一个对照着学生的学号去找,这种方式过于麻烦,我们需要用一种方式将这些数据拼接起来,方便我们查看。
思路:
- 分析需求:分析查询的字段来自于那些表
- 连接方式:确定使用哪种连接方式查询(确定交叉点,即这两个表中哪些数据是相同的)
根据分析两张表结构,我们可以判断的条件为:学生表中的studentNo = 成绩表中的studentNo
#使用inner join联表查询
select s.`studentNo`,`studentName`,`subjectNo`,`studentResult`
from `student` as s inner join `result` as r
where s.`studentNo` = r.`studentNo`
#使用right join联表查询
select s.`studentNo`,`studentName`,`subjectNo`,`studentResult`
from `student` as s right join `result` as r
on s.`studentNo` = r.`studentNo`
#使用left join联表查询
select s.`studentNo`,`studentName`,`subjectNo`,`studentResult`
from `student` as s left join `result` as r
where s.`studentNo` = r.`studentNo`
-
join on
连接查询 -
where
等值查询
操作 | 描述 |
---|---|
inner join | 如果表中至少有一个匹配,就返回,如果两张表都有,就确定是哪张表即可 |
left join | 即使右表中没有值与左表匹配,也会返回左表所有的值 |
right join | 即使左表中没有值与右边的值相匹配,也会返回右表所有的值 |
如果我们需要查两张以上的表,先对前面两张表进行查询,再将查询到的结果与第三张表进行连接。
#查询学生的学号,姓名,科目,成绩(来自三张表)
SELECT stu.studentno,studentname,sub.subjectname,studentresult
from student stu INNER join result res
on stu.studentno = res.studentno
right join subject sub
on stu.studentno = res.studentno
5.七种join理论:
6.自连接查询
自连接:顾名思义就是自己和自己连接,核心就是将一张表拆为两张一样的表即可。
我们在现有的school数据库中新建一个表category
drop table if exists `category`
CREATE TABLE if not exists `category`(
`categoryid` INT(3) NOT NULL COMMENT'id',
`pid` INT(3) NOT NULL COMMENT'父id 没有父则为1',
`categoryname` VARCHAR(10) NOT NULL COMMENT'种类名字',
PRIMARY KEY (`categoryid`)
) ENGINE=INNODB CHARSET=utf8;
INSERT INTO `category` (`categoryid`, `pid`, `categoryname`) VALUES (2, 1, "信息技术"), (3, 1, "软件开发"),(5, 1, "美术设计"), (4, 3, "数据库"),(8, 2, "办公信息"), (6, 3, "web开发"), (7, 5, "ps技术");
我们分析这张表,可以看出,在这张表内实现了分级,例如web开发,它的id为6,但是它的父id为3,而id为3的软件开发父id又为1。我们拆分一下这张表。
- 父表
categoryid | categoryname | pid |
---|---|---|
2 | 信息技术 | 1 |
3 | 软件开发 | 1 |
5 | 美术设计 | 1 |
- 子表
categoryid | categoryname | pid |
---|---|---|
4 | 数据库 | 3 |
8 | 办公信息 | 2 |
6 | web开发 | 3 |
7 | 美术设计 | 5 |
操作:查询父类对应的子类关系
父类 | 子类 |
---|---|
信息技术 | 办公信息 |
软件开发 | 数据库 |
软件开发 | web开发 |
美术设计 | ps技术 |
我们要进行查询,这应该是我们想要的查询结果。
对于都在一个表中的字段,我们就使用自连接查询。
select a.categoryname 科目类别,b.categoryname 课程
from category a inner join category b
on a.categoryid = b.pid
7.分页和排序查询
(1)排序查询
- 升序(asc):
查询结果根据成绩来升序排序
select * from `result` ORDER BY `studentresult` asc
- 降序(desc):
select * from `result` ORDER BY `studentresult` desc
- order by:通过那个字段排序
- desc、asc:desc降序,asc升序
(2)分页查询
思考一下:为什么要用分页查询?
我们在一个很庞大的数据库中去寻找数据,如果要全部展示,数据库的压力会非常大,而且我们查找数据也极不方便,因此,我们需要用到分页。
- 使用limit进行分页查询
SELECT * from subject limit 0,10
- limit a, b:从
索引为 a
开始显示 b 条
数据
练习题:
查询科目大于60分的所有学生,显示前10条,并降序排列,字段只显示学生名称,科目名称,成绩
SELECT studentname 学生姓名,sub.subjectname 科目名称,studentresult 学生成绩
from student stu inner join result res
on stu.studentno = res.studentno
inner join subject sub
where res.subjectno = sub.subjectno
and studentresult>60 ORDER BY studentresult desc limit 0,10
8.子查询和嵌套查询
之前我们在写sql,查询条件中的值都是固定的,如果将条件中的值换成计算出来的话,就是子查询了。
本质:在where条件下嵌套一个查询语句
示例:
#查询高等数学-1的所有考试结果(包含学号,姓名,科目编号,成绩),按照成绩降序排列
--使用连接查询
select stu.studentno,studentname,res.subjectno,studentresult
from student stu
inner join result res
on stu.studentno = res.studentno
inner join subject sub
on res.subjectno = sub.subjectno
where subjectname = '高等数学-1'
order by studentresult desc
--使用子查询
select stu.studentno,studentname,res.subjectno,studentresult
from student stu
inner join result res
on stu.studentno = res.studentno
where res.subjectno = (select subjectno from subject where subjectname = '高等数学-1')
order by studentresult desc
再来一题
#查询科目为高等数学-2且科目分数不小于80分的学生的学号和姓名
#联表查询方式
select distinct stu.studentno,studentname
from student stu
inner join result res
on stu.studentno = res.studentno
inner join subject sub
on res.subjectno = sub.subjectno
where subjectname = '高等数学-2'
and studentresult >= 80
#子查询方式一、
select stu.studentno,studentname
from student stu
inner join result res
on stu.studentno = res.studentno
where subjectno = (
select subjectno from subject where subjectname='高等数学-2'
)
and studentresult >=80
#子查询方式二、
select studentno,studentname from student where studentno in (
select studentno from result where subjectno = (
select subjectno from subject where subjectname = '高等数学-2'
) and studentresult >= 80
)
#查询科目有“高等数学”关键字的成绩前五名同学的信息(学号,姓名,分数)
select stu.studentno,studentname,studentresult
from student stu inner join result res
where subjectno in (
select subjectno from subject where subjectname like "高等数学%"
) order by studentresult desc limit 0,5