4.多表查询

多表查询

广义笛卡尔积运算

在这里插入图片描述

内连接运算

θ连接 --join on

–求学生以及其选修课程的情况。
----92

select *   
from xs,cj
where xs.sno=cj.sno;

----SQL99标准:(推荐)

select *
from xs join cj on xs.sno=cj.sno ;

–上面例子加一个条件dept=计算机

select *
from xs join cj on xs.sno=cj.sno
where dept='计算机';

–查找选修了“计算机基础”课程
–且成绩在80分以上的学生学号、姓名、课程名及成绩。

select xs.sno,sname,cname,grade
from xs,kc,cj
where xs.sno=cj.sno and kc.sno=cj.sno 
and cname='计算机基础' and grade>80;
select xs.sno,sname,cname,grade
from xs join CJ on xs.sno=cj.sno join kc on kc.sno=cj.sno 
where cname='计算机基础' and grade>80;
自连接

在这里插入图片描述

–求年龄大于王燕的所有学生的姓名、专业名和出生日期。

select b.sname,b.dept,b.birthday
from xs a join xs b on a.sno<>b.sno
where a.sname='王燕' and a.birthday>b.birthday;

---- 先筛选 a学生表里只剩下一条王燕的记录,要求b学生表的学生生日小于a表
----后连接 b表a表出去重复的王燕就是答案

外连接

在这里插入图片描述

–左连接 查找未选修任何课程的学生。

select *
from xs a left join cj b on a.sno=b.sno
where b.sno is null;

自然连接

–在FROM子句中采用如下表现形式:NATURAL JOIN,结果会把重复字段去掉;
----natural 不能用限定词sql

查找选修计算机基础的学生

select  *
from xs natural join cj
where cname='计算机基础';

----等值连接解决也可以,using不能有限定词

select  *
from xs join cj using(sno) join kc using(cno)
where cname='计算机基础';

–一些改造 运用

–查找选修了“计算机基础”课程
–且成绩在80分以上的学生学号、姓名、课程名及成绩。

select sno,sname,cname,grade
from xs NATURAL join CJ NATURAL join kc 
where cname='计算机基础' and grade>80;

select sno,sname,cname,grade
from xs join CJ using(sno) join kc using(cno)
where cname='计算机基础' and grade>80;

查找未选修任何课程的学生。

select *
from xs natural join cj 
where b.sno is null;

求计算机专业的学生以及其选修课程的情况

select *
from xs natural join cj 
where dept='计算机';

子查询

在这里插入图片描述在这里插入图片描述

----查找选修离散数学的学生的学号。

select sno
from kc natural join cj 
where cname='离散数学';
select sno from cj
where con = (select cno from kc where cname='离散数学');

select cno from kc where cname=‘离散数学’; --在课程表里找到课程名是离散数学的课程号

----子查询求年龄大于王燕的所有学生的姓名、专业名和出生日期。

select sname,dept,birthday from xs
where birthday <
(select birthday from XS 
where sname='王燕' );

----查找选修离散数学的学生的姓名。(返回的是集合不是单值)
------先解决 查找 课程名为离散数学的课程号

select cno
from kc where cname='离散数学';

------再解决 查找 选修离散数学的学生的学号。

select sno from cj where cno =
                  (select cno
                   from kc where cname='离散数学');

------最后

select sname from xs 
where sno in
          (select sno 
          from cj  
          where cno =
                     (select cno 
                     from kc where cname='离散数学'));

----查找比所有计算机系的学生年龄都大的学生(< all)

select sno,sname,birthday
from xs
where dept<>'计算机'
and birthday<all(select birthday from xs where dept='计算机');

------等价于-----

select sno,sname,birthday
from xs
where dept<>'计算机'
and birthday<(select main(birthday) from xs where dept='计算机');

----查找课程号206的成绩不低于课程号101的最低成绩的学生的学号
---------课程号206的成绩

select grade from cj where cno='206';

---------课程号101的成绩

select grade from cj where cno='101';

---------课程号101的最低成绩

select min(grade) from cj where cno='101';

--------成绩满足条件的成绩

select grade from cj where cno='206' 
and grade>=
          any(select grade from cj where cno='101');

–min

select grade from cj where cno='206' 
and grade > 
          (select min(grade)from cj where cno='101');----找到101课程所有成绩

-----------最终结果

select sno from cj
where grade in (select grade from cj where cno='206' 
                and grade>=
                           any(select grade from cj where cno='101'));
子查询的位置
子查询放在WHERE子句中

----求与程明同系,或年龄大于王燕的学生的信息

select * from xs
where dept=(select dept from xs where sname='程明') 
or birthday<(select birthday from xs where sname='王燕');
子查询放在SELECT中

----求每个学生的学号、姓名、学分及最高学分。

select sno,sname,totalcredit,(select max(totalcredit) from xs)
from xs;
子查询放在FROM中

–求学分最高的前5名学生。
-----学分从高到低排列的学生表,nvl(totalcredit,0)把总学分为空的转换成0

select * from xs order by nvl(totalcredit,0) desc;

----排好的学生表放在from中

select *
from (select * from xs order by nvl(totalcredit,0) desc)
where rownum<6;  ---- 伪列rownum只能用小于号不能用大于号

相关子查询

在这里插入图片描述

–查询所有选修了102号课程的学生姓名。
-----子查询

select sname
from xs
where sno in (select sno from kc where cno='102');

----相关子查询用到了外查询exists

select sname 
from xs
where  exists (select * from cj where xs.sno=cj.sno and cno='102');

-------先执行外查询select * from cj where xs.sno=cj.sno and cno=‘102’
-------当此外查询语句为真时 exits 返回真
-------执行select sname from xs where ture; 返回sname

在这里插入图片描述

–求出选修全部课程学生姓名

-----这个成绩表里的这条信息,学号对应学生表里的学号,课程号对应课程表里的课程号
-----这个学生选修过这门课

SELECT * FROM cj WHERE (sno= xs.sno AND cno=kc.cno);

-----不存在这样的课程 (这个学生选修过)

SELECT cno FROM kc 
WHERE NOT EXISTS
               (SELECT * FROM cj
                 WHERE sno= xs.sno AND cno=kc.cno);

-----不存在这样的课程,这个学生没有选修过
-----说明这个学生选修了全部课程

SELECT sname FROM  xs
WHERE NOT EXISTS  (SELECT cno 
                   FROM kc 
                   WHERE NOT EXISTS
                                  (SELECT *
                                    FROM cj
                                    WHERE sno= xs.sno AND cno=kc.cno));

----查询选修程明同学选修的所有课程的学生名
–只需要替换kc 为程明同学选修的kc

--select cno from xs natural join kc where sname='程明'
--xs natural join kc 自然连接学生表和课程表
SELECT sname FROM  xs
WHERE NOT EXISTS  (SELECT cno 
                   FROM (select cno from xs natural join kc where sname='程明' ) 
                   WHERE NOT EXISTS
                                  (SELECT *
                                    FROM cj
                                    WHERE sno= xs.sno AND cno=kc.cno));

传统集合运算的实现

在这里插入图片描述在这里插入图片描述在这里插入图片描述

–求总学分在第五名到第八名的学生

select sno from (select * from xs order by nvl(totalcredit,0) desc )
where rownum<=8
minus
select sno from (select * from xs order by nvl(totalcredit,0) desc )
where rownum<5;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值