查询和01号学⽣学习的课程完全相同的其他同学的信息查询所⽤到的各表表结构见此博客:
查询和01号同学学习的课程完全相同的其他同学的信息:
代码:
select * from student where sid in
(select sid from grade2 where sid not in
(select sid from grade2 where cid not in (select cid from grade2 where sid='01'))
group by sid
having count(*)=(select count(*) from grade2 where sid='01') and sid != '01');
代码解析:
⾸先重新创建⼀个成绩表garde2⽤于测试上述代码,grade2表和student表的表结构均保持不变。
# 创建成绩表grade2:
create table grade2(
sid varchar(10),
cid varchar(10),
score decimal(4,1)
)engine myisam charset utf8;
# 向成绩表grade2中插⼊数据:
insert into grade2 values
('01','01',80),
distinct查询('01','02',90),
('02','01',70),
('02','02',60),
('02','03',80),
('02','04',85),
('03','01',80),
('03','02',80),
('03','03',80),
('03','04',61),
('04','01',75),
('04','02',30),
('05','01',76),
('05','02',87),
('05','03',99),
('05','04',75),
('06','01',31),
('06','02',65),
('06','03',34),
('07','02',89),
('07','03',98),
('09','02',82),
('10','01',88),
('10','02',90),
('13','01',59),
('13','02',79),
('13','04',81);
查看grade2表的详细信息:
select * from grade2;
由上图可知,和01号学⽣学习的课程完全相同的其他学⽣的学⽣编号sid包括04和10;
下⾯从最内层开始逐步解析前⽂的查询代码:
查询出01号学⽣选修的所有课程的编号:
select cid from grade2 where sid='01';
查询出选修了01号学⽣没有选修课程的学⽣编号:
select sid from grade2 where cid not in (select cid from grade2 where sid='01');
上述查询结果中有重复的sid,这是因为有的学⽣选修的01号学⽣没选修课程不只⼀门。可以使⽤distinct关键字对sid进⾏去重处理。查询选修的课程是01号学⽣选修课程的⼦集的学⽣编号:
select sid from grade2 where sid not in
(select sid from grade2 where cid not in (select cid from grade2 where sid='01'));
从上述查询结果中,筛选出选修的课程数量与01号学⽣选修的课程数量相等的其他学⽣的编号:
select sid from grade2 where sid not in
(select sid from grade2 where cid not in (select cid from grade2 where sid='01'))
group by sid
having count(*)=(select count(*) from grade2 where sid='01') and sid != '01';
以上述查询结果为筛选条件,从student表中查询出与01号学⽣学习的课程完全相同的其他学⽣的信息:
select * from student where sid in
(select sid from grade2 where sid not in
(select sid from grade2 where cid not in (select cid from grade2 where sid='01'))
group by sid
having count(*)=(select count(*) from grade2 where sid='01') and sid != '01');
⼩结:
看到题⽬后想了很久,最初的想法是直接出和" 01 "号的同学学习的课程完全相同的其他同学的编号,但没写出来能实现这种效果的SQL 语句。最后在⽹上到了⼀篇博客,前⾯代码的基本逻辑即来
源于此:
下⾯是我从代码中总结出的思路:
01号之外的其他学⽣可以分成两个⼤类,⼀类是选修了01号学⽣没有选修的课程的学⽣,另⼀类学⽣选修的课程是01号学⽣选修的课程的⼦集。采⽤逆向思维,可以先出选修了01号学⽣没选课程的学⽣编号,然后以01号学⽣选修的课程数量为筛选条件,从剩下的选修的课程是01号学⽣选修的课程的⼦集这类学⽣中筛选出与01号学⽣所选课程完全相同的学⽣编号,此编号包含了01,以剔除了01之后的编号为筛选条件,从student表中选出和01号同学学习的课程完全相同的其他同学的信息。
另:下⾯评论中的朕⽔朋友提供了另⼀种很巧妙的查询思想:这是⼀种正向查询的思想,先筛选出其他学⽣中选修的课程数量和01号学⽣选修的课程数量相同的学⽣的学⽣编号和所修课程编号,然后将筛选结果与01号学⽣选修的课程编号进⾏内连接,然后再根据01号学⽣选修课程的数量做最后的筛选。
查询代码:
select * from student where sid in
(select sid from
(select sid,cid from grade2 where sid in
(select sid from grade2 where sid !='01' group by sid
having count(*)=(select count(*) from grade2 where sid='01' group by sid))) as t1
inner join (select cid from grade2 where sid='01') as t2
on t1.cid = t2.cid
group by t1.sid
having count(*)=(select count(*) from grade2 where sid='01')
)

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。