我不知道为什么这个查询意味着这句话

时间:2019-04-19 09:41:04

标签: sql

select distinct S.ID, S.name
from student as S
where not exists (
    (select course_id from course where dept_name = ’Biology’)
    except
    (select T.course_id from takes as T where S.ID = T.ID)
);

此查询在我的书中表示

  

“查找所有修过生物学所有课程的学生   部门”

表如下:
学生(ID,姓名,部门名称,tot_cred)
接受(ID,course_id,sec_id,学期,学年,年级)
课程(课程ID,标题,部门名称,学分)

我以为查询不起作用,因为学生表没有课程ID。

为什么该查询的执行与上述相同?

2 个答案:

答案 0 :(得分:2)

  

我以为查询不起作用,因为学生表没有课程ID。

请注意,除了表192.168.1.xIPROUTER = (Left(IP, 10)) & (Mid(IP, 11, 3) + 5) )或表course_idcourse)之外,从未引用select course_id from course。该查询从未引用过takes,因此您的问题掩盖了您对该查询的误解。

查询有点混乱,因为它有效地使用了双重否定。 select T.course_id from takes as T子句或多或少说:“如果所有学生都参加了所提供的生物学课程,并删除了该学生所参加的所有课程,则将所有学生都找到哪里,结果将是空的。”

student.course_id

如果我们修读所有提供的生物学课程,并删除该学生已修读的课程,而结果为空集,则唯一可能的解释是该学生已修读所有提供的生物学课程。 (此外:也有可能没有提供生物学课程,在这种情况下,学生仍会修读所有提供的生物学课程-这称为vacuous truth。)

答案 1 :(得分:1)

查询的意思是:“生物学系中没有一个学生没有修过的课程”。

第二个子查询(在except之后)正在获取该学生参加的所有课程。这些已从生物学系的所有课程中删除。因此,如果某个学生修完了该系的所有课程,那么结果将是没有行。否则,结果是学生未参加的行。

select distinct极具误导性。学生表不应重复。

我更喜欢对这些类型的查询使用聚合:

select t.student_id
from takes t join
     course c
     on t.course_id = c.course_id 
where c.dept_name = 'Biology'
group by t.student_id
having count(distinct t.course_id) = (select count(*) from course c2 where c2.dept_name = 'Biology');

(至少对我而言),这里的逻辑更加清晰地符合“学生将修完生物学系的所有课程”。