查询和01号学生学习的课程完全相同的其他同学的信息

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_36211042/article/details/102731433

今天读了几篇博客:https://blog.csdn.net/qq_41080850/article/details/84593860

https://www.cnblogs.com/fengyunlishi/archive/2012/10/18/2730051.html

https://blog.csdn.net/qq_41080850/article/details/84648897#comments

题目和DDL贴一下,SQL在线练习网址(http://sqlfiddle.com/),方便动手实践:

--1.学生表
student(sid,sname,sage,ssex)
--sid 学生编号,sname 学生姓名,sage 出生年月,ssex 学生性别
--2.课程表
course(cid,cname,tid)
--cid 课程编号,cname 课程名称,tid 教师编号
--3.教师表
teacher(tid,tname)
--tid 教师编号,tname 教师姓名
--4.成绩表
grade(sid,cid,score)
--sid 学生编号,cid 课程编号,score 分数

题目:查询和01号学生学习的课程完全相同的其他同学的信息。

# 创建学生表:
create table student (
sid varchar(10),
sname varchar(10),
sbirth datetime,
sgender char(1)
)engine myisam charset utf8;
 
# 向学生表中插入数据:
insert into student values
('01','赵雷','1990-01-01','男'),
('02','钱枫','1990-12-21','男'),
('03','孙思邈','1990-12-16','男'),
('04','李四','1990-12-06','男'),
('05','周梅','1991-12-01','女'),
('06','吴兰','1992-01-01','女'),
('07','郑珠','1989-01-01','女'),
('09','张三','2017-12-20','女'),
('10','李四','2017-12-16','女'),
('11','李四','2012-06-06','女'),
('12','赵雷','2013-06-13','男'),
('13','孙琦','2014-06-01','女');
 
 
# 创建科目表:
create table course(
cid varchar(10),
cname varchar(10),
tid varchar(10)
)engine myisam charset utf8;
 
# 向科目表中插入数据:
insert into course values
('01','语文','02'),
('02','数学','01'),
('03','英语','03'),
('04','政治','04');
 
 
# 创建教师表:
create table teacher(
tid varchar(10),
tname varchar(10)
)engine myisam charset utf8;
 
# 向教师表中插入数据:
insert into teacher values
('01','张衡'),
('02','李文'),
('03','吴迪'),
('04','王珊');
 
 
# 创建成绩表:
create table grade(
sid varchar(10),
cid varchar(10),
score decimal(4,1)
)engine myisam charset utf8;
 
# 向成绩表中插入数据:
insert into grade values
('01','01',80),
('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),
('04','03',20),
('04','04',45),
('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);

博主们的解答,读后很受启发,特别是Backcanhave7博主对各习题的逐步推导,层次分明。

自己想了一下这道问题,有了一些总结:

针对这类匹配问题(匹配数量和内容),例如这道题,需要和学号01的课程完全相同,可以使用连接查询来进行匹配。

一般来说,在C、Java语言中,我们用循环来遍历两个list,然后判断size()、各个元素是否相同。在SQL中,这种遍历比较的思想,可以用笛卡尔积来实现,具体来说就是内连接(inner join)、外连接(left/right outer join)、交叉连接(cross join)。

(1)内连接(原创是 朕水)

这是一种正向查询的思想,先筛选出其他学生中选修的课程数量和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')
)

(2)外连接

SELECT * FROM student WHERE sid IN(
	SELECT g1.sid FROM grade g1 
	LEFT JOIN (SELECT DISTINCT cid FROM grade WHERE sid=01) g2 ON g1.cid=g2.cid
	WHERE g1.sid<>01
	GROUP BY g1.sid
	HAVING COUNT(g1.cid)=(SELECT DISTINCT COUNT(cid) FROM grade WHERE sid=01) AND COUNT(g2.cid)=COUNT(g1.cid)    -- 自身课程数=01课程数,且,自身课程=01课程
);

类似于内连接,使用外连接也是一种正向思维,逐步求解。我的具体思路如下:

a.读题可以直观地得到以下两个值:

       --01号学生的课程:SELECT DISTINCT cid FROM grade WHERE sid=01

        -- 01号学生的课程总数:SELECT DISTINCT COUNT(cid) FROM grade WHERE sid=01

b.选出和01号学生课程完全相同的学生,主要是得到符合条件的sid,就能查出学生信息。所以用所有学生的选课和01号学生的课程逐个作比较。因为左连接可以更好地保留那些不符合条件的学生,以备进一步筛选。

SELECT g1.sid FROM grade g1 
	LEFT JOIN (SELECT DISTINCT cid FROM grade WHERE sid=01) g2 ON g1.cid=g2.cid

 c.然后逐步添加筛选条件,在having子句中:

COUNT(g2.cid)=COUNT(g1.cid)

其实应该写作COUNT(g2.cid)=(SELECT DISTINCT COUNT(cid) FROM grade WHERE sid=01),保证 筛选出的学生的课程,包含了01学生所选的所有课程(即:01号学生的课程 是 某个学生的课程 的子集)。

COUNT(g1.cid)=(SELECT DISTINCT COUNT(cid) FROM grade WHERE sid=01)

这个筛选条件保证 学生的课程数=01号学生的课程数,防止 01号学生的课程 是 某个学生的课程 的真子集。

是子集但不是真子集,所以只能是相等。

读完如果有用,顺便求个赞~

猜你喜欢

转载自blog.csdn.net/qq_36211042/article/details/102731433