针对这类匹配问题(匹配数量和内容),例如这道题,需要和学号01的课程完全相同,可以使用连接查询来进行匹配。
    一般来说,在C、Java语言中,我们用循环来遍历两个list,然后判断size()、各个元素是否相同。在SQL中,这种遍历比较的思想,可以用笛卡尔积来实现,具体来说就是内连接(inner join)、外连接(left/right outer join)、交叉连接(cross join)。
    (1)外连接

    1. SELECT s.* FROM Student as s
    2. WHERE s.s_id IN(
    3. SELECT sc1.s_id FROM Score sc1
    4. LEFT JOIN (SELECT DISTINCT c_id FROM Score WHERE s_id=01) sc2 ON sc1.c_id=sc2.c_id
    5. WHERE sc1.s_id<>01
    6. GROUP BY sc1.s_id
    7. HAVING COUNT(sc1.c_id)=(SELECT DISTINCT COUNT(c_id) FROM Score WHERE s_id=01) AND COUNT(sc2.c_id)=COUNT(sc1.c_id) -- 自身课程数=01课程数,且,自身课程=01课程
    8. );

    a.读题可以直观地得到以下两个值:
    —01号学生的课程:SELECT DISTINCT c_id FROM Score WHERE s_id=01
    — 01号学生的课程总数:SELECT DISTINCT COUNT(c_id) FROM Score WHERE s_id=01
    b.选出和01号学生课程完全相同的学生,主要是得到符合条件的sid,就能查出学生信息。所以用所有学生的选课和01号学生的课程逐个作比较。因为左连接可以更好地保留那些不符合条件的学生,以备进一步筛选。
    SELECT sc1.s_id FROM Score sc1
    LEFT JOIN (SELECT DISTINCT c_id FROM Score WHERE s_id=01) sc2 ON sc1.c_id=sc2.c_id
    c.然后逐步添加筛选条件,在having子句中:
    COUNT(sc2.c_id)=COUNT(sc1.c_id)
    其实应该写作COUNT(sc2.c_id)=(SELECT DISTINCT COUNT(c_id) FROM Score WHERE s_id=01),保证 筛选出的学生的课程,包含了01学生所选的所有课程(即:01号学生的课程 是 某个学生的课程 的子集)。
    COUNT(sc1.c_id)=(SELECT DISTINCT COUNT(c_id) FROM Score WHERE s_id=01)
    这个筛选条件保证 学生的课程数=01号学生的课程数,防止 01号学生的课程 是 某个学生的课程 的真子集。
    是子集但不是真子集,所以只能是相等。

    (2)内连接
    这是一种正向查询的思想,先筛选出其他学生中选修的课程数量和01号学生选修的课程数量相同的学生的学生编号和所修课程编号,然后将筛选结果与01号学生选修的课程编号进行内连接,然后再根据01号学生选修课程的数量做最后的筛选。

    1. select * from student where sid in
    2. (select sid from
    3. (select sid,cid from grade2 where sid in
    4. (select sid from grade2 where sid !='01' group by sid
    5. having count(*)=(select count(*) from grade2 where sid='01' group by sid))) as t1
    6. inner join (select cid from grade2 where sid='01') as t2
    7. on t1.cid = t2.cid
    8. group by t1.sid
    9. having count(*)=(select count(*) from grade2 where sid='01')
    10. )