为什么我需要SQL中的两个表副本?

时间:2014-11-17 15:11:32

标签: mysql sql sqlite

SQL初学者,在我的大学课程中,我们有以下架构。


Student(snum:integer,sname:string,major:string,level:string,age:integer)

Class(name:string,meets_at:string,room:string,fid:integer)

已注册(snum:integer,cname:string)

Faculty(fid:integer,fname:string,deptid:integer)


其中一项练习如下:

查找所有同时参加两个课程的学生的姓名。

以下是它的SQL语句

SELECT DISTINCT S.SNAME

FROM STUDENT S

WHERE S.SNUM IN (SELECT E1.SNUM

             FROM ENROLLED E1, ENROLLED E2, CLASS C1, CLASS C2

              WHERE E1.SNUM = E2.SNUM AND E1.CNAME <> E2.CNAME

               AND E1.CNAME = C1.NAME

              AND E2.CNAME = C2.NAME AND 

              C1.MEETS_AT = C2.MEETS_AT);

在我的子查询中,为什么要使用关系ENROLLED和CLASS的两个副本。

2 个答案:

答案 0 :(得分:1)

表声明两次的原因是比较同一查询中的表。

您必须拥有该表的两个副本才能将表与自身进行比较。

您的查询正在查看E1并在E2中检查它,其中StudentNumber相同但类的名称不同。

然后它查看C1表和C2表,找到类的名称......然后查看类meet_at是否相同。

您需要两个表的原因是您无法在同一查询中两次比较E1。在单个查询中,无法检查row1与同一列的其他行。

答案 1 :(得分:0)

子查询引用ENROLMENTS表两次,因为它需要检索多次注册的学生和CLASSES两次,因为它只需要检索已注册多个课程的学生。

考虑一个更简单的查询:

select C1.NAME, C2.NAME
from   CLASS C1, CLASS C2
where  C1.MEETS_AT = C2.MEETS_AT
and    C1.NAME <> C2.NAME;

这将为您提供同时会面的课程列表。有必要将完整的类集与自身进行比较,寻找具有相同MEETS_AT时间的类。最后一行排除了那些具有相同名称的类。

您的子查询会检索已注册多个同时开课的学生的学生编号列表:

SELECT E1.SNUM
  FROM ENROLLED E1, 
       ENROLLED E2, 
       CLASS C1, 
       CLASS C2
 WHERE E1.SNUM = E2.SNUM            -- the same student has enrolled twice
   AND E1.CNAME <> E2.CNAME         -- the enrollments are for difference classes
   AND E1.CNAME = C1.NAME           -- join the class table as C1 for the first enrollment
   AND E2.CNAME = C2.NAME           -- join the class table as C2 for the second enrollment
   AND C1.MEETS_AT = C2.MEETS_AT    -- match the start times for the two enrolled classes

只是出于对ANSI SQL等效的兴趣:

    select E1.SNUM
      from ENROLLED E1 
inner join ENROLLED E2 on E1.SNUM = E2.SNUM
inner join CLASS C1 on E1.CNAME = C1.NAME
inner join CLASS C2 on E2.CNAME = C2.NAME
     where E1.CNAME <> E2.CNAME
       and C1.MEETS_AT = C2.MEETS_AT

和Siyual一样,我更喜欢ANSI版本,但是如果你的大学以旧方式教学,我建议你现在坚持使用它。它的工作原理也很好,很多人仍然使用它。一旦理解了这些概念,就可以选择自己的偏好。