有人可以向我解释这三个SQL查询吗?

时间:2016-11-15 18:16:59

标签: mysql database database-design

我是一个数据库类,练习一些SQL问题,以提高我的技能。这是我用来引用问题的数据库模式(发布的解决方案是正确的,我只需要一些解释来更好地理解它们):

enter image description here

Q1:检索具有相同名字且与员工性别相同的受抚养人的每位员工的姓名。

SELECT E.FNAME, E.LNAME
FROM EMPLOYEE AS E
WHERE E.SSN IN (SELECT D.ESSN, FROM DEPENDENT AS D, WHERE E.FNAME = D.DEPENDENT_NAME AND D.SEX = E.SEX);

我对这个查询有点困惑。第一个FROM子句不应该包含“依赖D”吗?我们为什么要嵌套这个?我没有看到原因。似乎让事情变得更复杂。

Q2:检索没有任何家属的员工的姓名。

SELECT E.FNAME, E.LNAME
FROM EMPLOYEE AS E
WHERE NOT EXISTS (SELECT *, FROM DEPENDENT AS D, WHERE D.ESSN = E.SSN);

而不是使用WHERE NOT EXISTS,我们不能只使用NULL吗?

为什么要使用“WHERE NOT EXISTS”条款?我们不能只使用NULL吗?

问题3:列出至少拥有一名受抚养人的经理的姓名。

SELECT FNAME, LNAME
FROM EMPLOYEE
WHERE EXISTS(SELECT * FROM DEPARTMENT WHERE SSN = MGR_SSN)
WHERE EXISTS (SELECT * FROM DEPENDENT WHERE ESSN = SSN);

老实说,我不明白这个查询背后的基本原理。我得到了一些,但我很难解释它自己。 FROM子句不应包括DEPARTMENT和DEPENDENT吗?为什么它只包括EMPLOYEE?如果有人可以逐步引导我完成这个查询,并解释为什么我们使用这些WHERE EXISTS子句的方式,那将非常有帮助。

2 个答案:

答案 0 :(得分:1)

有人需要教授该课程使用适当的逗号。

Q1:不,你不希望第一个FROM在DEPENDENT上,你试图选择员工信息,而不是家属'。子查询用于查找与其父级具有相同名称和性别的家属的essn(父级ssn)值。

编辑:在进一步检查Q1查询后,它似乎相当复杂;几乎绝对不是获取这些信息的最佳方式。将子查询原样保留,使用EXISTS而不是IN是不够的,因为有可能存在与相关员工具有相同名称和性别的从属,而这实际上并不是员工的依赖。如果将AND D.ESSN = E.SSN添加到子查询的WHERE标准中,那么EXISTS将是一个有效的选择。然而,实际上没有办法“不相关”。子查询并不能说明所涉及的三个字段上的INNER JOIN是一个更好的选择(在极少数情况之外,一些nincompoop在他们自己之后命名多个同性别的家属;在在哪种情况下INNER JOIN仍然可能是更好的解决方案,但现在应该在SELECT中使用DISTINCT。)。

Q2:我不确定你打算如何使用NULL。

问题3:同样,您不会(或者至少不需要)从外部查询中的其他表中选择,因为您不需要结果中的数据。两个EXISTS条件(可能)使用相关子查询(可能效率/性能较差,JOIN通常要快得多);也许用这样的别名来写更明显:

SELECT e.FNAME, e,LNAME
FROM EMPLOYEE AS e
WHERE EXISTS(SELECT * FROM DEPARTMENT AS d WHERE e.SSN = d.MGR_SSN)
   AND EXISTS (SELECT * FROM DEPENDENT AS d WHERE d.ESSN = e.SSN);

(编辑:正如另一位回答者所指出的那样;您不能拥有多个WHERE'(同一"级别")查询。

或将其翻译成英文......

  

"给我姓名的员工姓名   经理的ssn与员工的ssn相同的部门   有一个依赖者,其父母的ssn与该父母的ssn相同   雇员' S"

答案 1 :(得分:1)

第一个不会运行。有许多,应该是:

SELECT E.FNAME, E.LNAME
FROM EMPLOYEE AS E
WHERE E.SSN IN (SELECT D.ESSN
                FROM DEPENDENT AS D
                WHERE E.FNAME = D.DEPENDENT_NAME 
                  AND D.SEX = E.SEX);

如果你问是否可以写成JOIN,是这样的:

SELECT DISTINCT E.FNAME, E.LNAME
FROM EMPLOYEE AS E
JOIN DEPENDENT D
  ON E.SSN = D.ESSN
 AND E.FNAME = D.DEPENDENT_NAME 
 AND D.SEX = E.SEX

第二个,再次过多,,是的,您可以检查NULL但需要使用LEFT JOIN

SELECT E.FNAME, E.LNAME
FROM EMPLOYEE AS E
LEFT JOIN DEPENDENT D
  ON E.SSN = D.ESSN
WHERE D.ESSN IS NULL   -- IF doesnt have any match, will only have a NULL row

第三个无法提供两个WHERE AND

SELECT FNAME, LNAME
FROM EMPLOYEE
WHERE EXISTS (SELECT * FROM DEPARTMENT WHERE SSN = MGR_SSN)
  AND EXISTS (SELECT * FROM DEPENDENT  WHERE ESSN = SSN);

首先exists告诉您员工也是经理。第二个exists告诉您员工有依赖