我有以下两种关系:
EMP是员工与他们的号码ENO,他们的姓名ENAME,他们的职位名称JOB,他们被雇用的日期,他们的工资SAL以及他们在DNO工作的部门号码的关系(参考DNO的forgein密钥)在DEPT)。
DEPT是部门与每个部门DNO的数量,部门DNAME的名称,部门DIR的主管(引用ENO的forgein密钥)的关系。
我的问题是:
查找具有相同工作和相同导演的员工的姓名,以及#Joe;#'
我的尝试是:
SELECT ENAME
FROM EMP, DEPT
WHERE EMP.DNO = DEPT.DNO
AND (DIR, JOB) IN (
SELECT DIR, JOB
FROM EMP, DEPT
WHERE ENAME = 'Joe'
AND EMP.DEPT = DEPT.DNO
)
AND ENO NOT IN (
SELECT ENO
FROM EMP, DEPT
WHERE ENAME = 'Joe'
AND EMP.DEPT = DEPT.DNO
)
我找到了这个问题的解决方案,但我无法达成一致。
这是我发现的:
SELECT ENAME
FROM EMP, DEPT
WHERE ENAME <> 'Joe'
AND EMP.DNO = DEPT.DNO
AND (DIR, JOB) = (
SELECT DIR, JOB
FROM EMP, DEPT
WHERE ENAME = 'Joe'
AND EMP.DEPT = DEPT.DNO
)
问题是,我们不得不考虑乔&#39;在结果中。但是乔&#39;哪个?
答案 0 :(得分:1)
你说的第二个解决方案是错误的。如果有两个'乔'它将无法正常工作。这就是为什么你应该根据唯一的ENO而不是非唯一的名称进行排除。第一个查询不会出于同样的原因。为了确定,您不能仅通过名称或标题或部门进行选择,因为这些可能是重复的。我们部门有三位Chris程序员。
此外,该连接语法已过时,因为在某些情况下它可能会导致数据库混淆。有关当前语法的说明,请参阅http://www.w3schools.com/sql/sql_join_inner.asp。
答案 1 :(得分:1)
您正在使用的逗号加入方式已经过时了很长时间。我认为以下就是你所追求的。我们的想法是为自己加入一张桌子。这是通过在此处提供表别名 - source
和twin
来完成的。
SELECT twin.ENAME
FROM EMP AS source
JOIN EMP AS twin ON twin.DNO = source.DNO AND twin.JOB = source.JOB
WHERE source.ENAME = 'Joe' AND source.ENO <> target.ENO
答案 2 :(得分:1)
看起来“导演”有可能领导多个部门。至少,信息模型似乎没有任何限制(即DIR
没有唯一约束)
据推测,我们通过查找EMP
中ENAME
属性等于'Joe'
的元组来识别员工'Joe'。
大概,我们会通过从DIR
关系中获取DEPT
属性的值来识别Joe的“导演”。
如果我们希望员工与Joe
处于“同一部门”,我们可以使用DNO
属性的值,...但是要求说“相同的导演”。所以,如果同一位导演负责多个部门,我们将会让所有部门由该主管领导。
然后,这是一个简单的问题,让所有员工都进入这些部门,并检查与乔的“工作”相匹配的“工作”。
SELECT e.ENAME
FROM EMP j
JOIN DEPT i
ON i.DNO = j.DNO
JOIN DEPT d
ON d.DIR = i.DIR
JOIN EMP e
ON e.DNO = d.DNO
AND e.JOB = j.JOB
WHERE j.ENAME = 'Joe'
同样,如果我们只想要与Joe在“同一部门”中的员工,我们可以免除其中一个对DEPT
的引用。如果Joe的主管负责另一个部门,那么结果会有所不同,并且其他部门的员工也有相同的工作......该员工将被排除在此查询之外:
SELECT e.ENAME
FROM EMP j
JOIN DEPT i
ON i.DNO = j.DNO
-- JOIN DEPT d
-- ON d.DIR = i.DIR
JOIN EMP e
-- ON e.DNO = d.DNO
ON e.DNO = i.DNO
AND e.JOB = j.JOB
WHERE j.ENAME = 'Joe'
如果需要从结果集中排除Joe
,那么我们可以在WHERE子句中添加另一个谓词。如果我们不假设ENAME
不能有NULL值......
AND ( e.ENAME IS NULL OR e.ENAME <> 'Joe')