sql

时间:2016-10-16 09:19:16

标签: sql database

在课堂上,教授说SQL语言并不提供“为所有人”操作。 为了使用'为所有',你必须使用'不存在(X除了Y)'

此时,我无法弄清楚为什么'为所有'与'不存在(X除了Y)'的含义相同

我举个例子关系:

  • 当然( cID ,title,deptName,credit),
  • 教授( pID,cID,学期,年份 ,教室),
  • 学生( sID ,姓名,性别,deptName)

问:找到所有参加过“CS”部门提供的所有课程的学生姓名

答案是:

Select distinct 
  S.sid, S.name 
from 
  student as S 
where 
  not exists (
    (select cID from course where deptName = 'CS') 
    except
    (select T.cID from takes as T where S.sID = T.sID)
  );

你能给我具体的解释吗?

PS。对不起我的英语技能

4 个答案:

答案 0 :(得分:4)

你教授是对的。 SQL无法直接查询具有某种类型所有可能关系的所有记录。

查询记录具有某种类型的关系很容易。只需INNER JOIN这两张表即可完成。

但是在像“学生”到“学习”这样的M:N关系中,并不是那么简单。

要回答“哪位学生已经学习了所有课程”的问题,您必须找出可能存在哪些关系,然后确保所有这些关系实际存在

select distinct 
  S.sid, S.name 
from 
  student as S 
where 
  not exists (
    (select cID from course where deptName = 'CS') 
    except
    (select T.cID from takes as T where S.sID = T.sID)
  );

可翻译为

give me all students                    SELECT
for whom it is true:                    WHERE
that the following set is empty         NOT EXISTS
  (any course in 'CS')                  "all relations that can possibly exist"
  minus                                 EXCEPT
  (all courses the student has taken)   "the ones that do actually exist"

换句话说:在所有可能的关系中,没有不存在的关系。

在不支持EXCEPT的情况下,还有其他方法可以表达相同的思想,可以在数据库系统中使用。

例如

select
  S.sid,
  S.name
from 
  student as S
  inner join takes as T on T.sID = S.sID
  inner join course as C on C. cID = T. cID
where
  c. deptName = 'CS' 
group by
  S.sid,
  S.name
having
  count(*) = (select count(*) from course where deptName = 'CS');

答案 1 :(得分:0)

从您的表定义和要求中,不清楚示教表的用途是什么。你想要那些已经参加了CS' CS'提供的所有课程的学生名单。部门。对于学生课程表就足够了。

SELECT name
FROM
(
SELECT B.name, A.cid
FROM course A
INNER JOIN student B ON A.deptName = B.deptName
WHERE A.deptName = 'CS'
GROUP BY A.cid, B.name
) A
GROUP BY name
HAVING COUNT(name) >= (SELECT COUNT(cid) FROM course WHERE deptName = 'CS')

内部查询只选择那些已经参加过CS&C 39的任何课程的学生。我和小组一起确保如果学生两次上同一课程,他们将被计为一行。接下来我只选择那些学生参加CS' CS'部。

我认为您在正确理解您的要求方面存在一些差距。在您的要求中,未指定与示教表的关系。

答案 2 :(得分:0)

  

问:找到所有已经参加CS' CS'   系

NOT EXISTS returns true if the query passed to it contains 0 records.

在这种情况下,来自NOT EXISTS的子查询选择' CS'中提供的所有课程,并从该结果集中减去特定学生所采用的所有课程。 如果学生已完成所有课程,则except将删除所有课程,子查询将返回0条记录,与NOT EXISTS配对将为您提供特定学生的真实记录,并将显示在最终结果集。

答案 3 :(得分:0)

简史:Codd发明了关系模型(RM),有些人基于RM创建了一个DBMS,以证明RM产品可以具有高性能,并且基于该DBMS出现了SQL语言(即不直接基于RM) )。

Codd提出了一组原始运算符来定义数据库是否是关系完整的。他的代数包括product,其中两个关系“相乘”以形成一个组合关系;这使它成为CROSS JOIN的SQL。 [附注:人们将此运算符称为“笛卡尔积”,从而产生一组有序对。但是,RM中的product会产生关系(与所有关系运算符一样),CROSS JOIN会导致表达式(松散地说)。]

Codd的代数还包括一个division运算符。我想这个想法是,我们应该能够得到product的结果和其中一个关系并使用运算符来产生另一个关系。但它当然也有一些实际用途。在他的书中找到Chris Date's parts and suppliers database之后,它通常表示为“供应所有产品的供应商”。 SQL缺少显式除法运算符,因此我们需要使用其他运算符来获得所需的结果。

请注意,two flavours of division是精确分部(“供应我们感兴趣的所有部件的供应商,不再是”)和剩余分部(“至少供应我们感兴趣的所有部件的供应商”)并且可能更多“)。我倾向于警惕这里没有提到“分裂”这个名称的答案,或者你需要决定是否需要处理余数。

你教授的回答背后的想法是双重否定(数学和英语),即如果“没有我不供应的部分”的陈述对于给定的供应商是正确的,则该供应商将在结果中。

注意Codd省略的运算符(例如renamesummerize)现在可以在SQL中找到,所以很遗憾我们还在等division