主题:sql的集合运算
一、表与集合
表(查询结果):记录行集合
集合中的元素:行
集合中运算:
-
属于:可以把行元素看成只有要一行的集合
-
差:minus
-
并:union/union all
-
交:intersect,mysql要代码实现
-
相等:要代码实现
关系:包含:A<B:中的元素都在B中,用差运算来实现,A-B为空就说明A是B的子集
二、并
1、基本语法
select A
union
select B
2、注意问题
- AB两个结果中列数顺序和类型都要相同
- all要注意
- 满足交换律
3、和or条件的比较
并运算效率高于or条件
---查找cjb中>90分的同学记录和学号为010101的同学的成绩记录
---方法一:
select b.*
from cjb b
where b.score>90
union
select a.*
from cjb a
where a.st_id='010101'
--方法二:
select b.*
from cjb b
where b.score>90 or b.st_id='010101'
三、差:minus
1、基本语法
select A
minus
select B
得出结果:A-B:A中的记录排除掉B中存在的
2、注意
- AB两个结果中列数顺序和类型都要相同
- 不满足交换律
- A-B为空则说明A是B的子集
3、应用:判断两个集合的包含关系,子集关系
结论:A-B为空,则A为B的子集,A包含于B
4、举例1
---查询学习了001课程,但是没有学习002课程的学生学号
select *
from cjb
where course_id='001' and course_id!='002'
---where条件是以行为单位进行判断,而题目需求是比较行与行之间
---方法一:用关联子查询
select a.st_id
from cjb a
where a.course_id='001' and not exists(
select b.*
from cjb b
where b.st_id=a.st_id and course_id='002'
)
---方法二:用差集:
---学习了001课程的学生学号
select st_id
from cjb
where course_id='001'
minus
--学习了001课程的学生学号
select st_id
from cjb
where course_id='002'
分析:
5、举例2
查找哪些学生学习了010106同学学过的所有课程
----先考虑查询010106同学所有的课程,010101同学哪些没有学,如果没有学的结果为空,则010101同学都学了
---方法一:
--第一步:
---如果这个结果为空,则说明010106同学所学的所有课程,010101同学都学了
select a.*
from cjb a
where a.st_id='010106' and not exists (
---如果查询结果为不空,则说明010106同学学习的当前课程,010101同学也学了
---如果查询结果为空,则说明010106同学学习的当前课程,但是010101同学没有学,则成立
select b.*
from cjb b
where b.course_id=a.course_id and b.st_id='010101'
)
第二步:在xsb表中,用每一个学号去代替上面的010101
select *
from xsb
where not exists(
---如果这个结果为空,则说明010106同学所学的所有课程,010101同学都学了
select a.*
from cjb a
where a.st_id='010106' and not exists (
---如果查询结果为不空,则说明010106同学学习的当前课程,010101同学也学了
---如果查询结果为空,则说明010106同学学习的当前课程,但是010101同学没有学,则成立
select b.*
from cjb b
where b.course_id=a.course_id and b.st_id=xsb.st_id
)
)
---方法二:
---第一步:
--两集合的差集:如果这个结果为空则06同学学习的所有课程,01同学都学了,那么06的集合-01的集合为空集:06学过课程,01都学了
select a.course_id from cjb a where a.st_id='010106'
minus
select b.course_id from cjb b where b.st_id='010101'
---第二步:
select *
from xsb
where not exists(
---如果这个结果是为空,说明06中学过的课程,xsb.st_id都学了,这个学号就满足要求
select a.course_id from cjb a where a.st_id='010106'
minus
select b.course_id from cjb b where b.st_id=xsb.st_id
)
分析:
四、交:intersect
1、基本语法
select A
intersect
select B
查询结果就是A交B
2、注意问题
- AB两个结果中列数顺序和类型都要相同
- 满足交换律
3、举例
查找010101和010106两个同学学过的相同课程
select a.course_id
from cjb a
where a.st_id='010101'
intersect
select b.course_id
from cjb b
where b.ST_ID='010106'
4、用差运算来实现交运算
A-(A-B)
5、课堂练习
---课堂练习:查找有哪些同学和010106同学学过的相同课程
select c.*
from cjb c
where c.st_id!='010106' and c.course_id in (
select e.course_id
from cjb e
where e.st_id='010106'
) and exists(
---如果结果不为空,则说明xsb.st_id这学生和010106同学学了相同课程
select a.course_id
from cjb a
where a.st_id=c.st_id
intersect
select b.course_id
from cjb b
where b.ST_ID='010106'
)
五、相等
1、注意问题
- sql没有相等运算,要自己代码实现
- A=B:A-B为空,同时B-A也为空
2、举例
---查询和010106同学选修完全一样的同学
---第一步:先考虑两个固定同学的课程是否完全一样
---检查010106同学和010101同学选修是否完全一样:所谓完全一样,是两同学学的课程不多少完全一致
--如果下面并运算的结果为空,则说明两个同学学习课程完全一样
(select a.course_id
from cjb a
where a.st_id='010106'
minus
select a.course_id
from cjb a
where a.st_id='010101'
)
union
(
select c.course_id
from cjb c
where c.st_id='010101'
minus
select d.course_id
from cjb d
where d.st_id='010106'
)
--第二步:用xsb中的学号代替010101
select *
from xsb
where not exists
---如果下面结果为空,则说明xsb.st_id这学生和010106同学学习的课程完全一样
(
(
select a.course_id
from cjb a
where a.st_id='010106'
minus
select b.course_id
from cjb b
where b.st_id=xsb.st_id
)
union
(
select c.course_id
from cjb c
where c.st_id=xsb.st_id
minus
select d.course_id
from cjb d
where d.st_id='010106'
)
)
where b.st_id=xsb.st_id
)
union
(
select c.course_id
from cjb c
where c.st_id=xsb.st_id
minus
select d.course_id
from cjb d
where d.st_id='010106'
)
)