集合运算在数据库中的应用

此文转载自:https://blog.csdn.net/ldzydwh/article/details/109991221

主题: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

AB集合关系图

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'
)

)


原文地址:https://www.cnblogs.com/phyger/p/14035280.html