【问题标题】:SQL queries on RELATION TABLE关系表上的 SQL 查询
【发布时间】:2023-03-18 04:47:02
【问题描述】:

员工可以在多个部门工作,每个部门可以有很多员工。因此需要一个关系表

表格:
EMP(eid,ename,eage,esalary)
作品(eid,did,pct_time)
Dept(did,dname,budget, managerid)

查找所有从事软件和硬件工作的员工:

SELECT e.ename FROM EMP e, Works w, Dept d 
WHERE e.eid = w.eid AND w.did = d.did AND d.did = 
(SELECT did FROM dept WHERE dname = 'Hardware' OR 'Software')  

按照乔恩的说法:

SELECT e.ename FROM EMP e OR Works w OR Dept d 
WHERE e.eid = w.eid AND w.did = d.did AND d.did = 
(SELECT did FROM dept WHERE dname = 'Hardware' OR 'Software')

而且我只是不知道如何确保 Works 中有两个条目用于同一 eid 下的硬件和软件。

【问题讨论】:

  • 您的FROM Emp e OR Works w OR Dept d 语法是对标准SQL 表示法的创新。我担心您使用的 DBMS 可能会对语法产生异常并拒绝您的 SQL 语句。

标签: sql


【解决方案1】:
select e.name
  from emp e, works h_w, dept h_d, works s_w, dept s_d
 where e.eid = h_w.eid
   and e.eid = s_w.eid
   and h_w.did = h_d.did
   and h_d.dname = 'Hardware'
   and s_w.did = s_d.did
   and s_d.dname = 'Software'

【讨论】:

  • 哇,这是很棒的信息,我不知道你可以用不同的名字给同一个表起别名。
  • 一般来说,您应该在 FROM 子句中使用“现代”(意思是 1992 年后)SQL 标准 JOIN 表示法,而不是“古代”(意思是 1992 年前)逗号分隔的表名列表.
  • @JonathanLeffler 虽然其中一个标签是“作业”,但这并不奇怪。许多学校仍然使用旧的连接语法教授 SQL。
【解决方案2】:

以下是解决问题的步骤:

  • 首先,获取works 表中部门为EITHER硬件或软件的所有行
  • 那么,对于任何员工,如果存在两行,则表示他/她同时为两个部门工作。
  • 对于任何员工,如果少于两行,则意味着他/她只为这两者之一工作,或者根本没有。
  • 我们需要检索正好有两行的员工。

所以我们首先可以从works 表中进行选择,将其与dept 表连接起来,并过滤掉任何非硬件或软件的部门:

SELECT a.*
FROM works a
INNER JOIN dept b ON a.did = b.did
WHERE b.dname IN ('Hardware','Software')

然后我们要做的是按每个员工分组,这将使我们能够访问汇总信息,例如每个员工的行数,或 sum/max/min/avg/等。的其他列。我们必须使用 count:

SELECT a.eid
FROM works a
INNER JOIN dept b ON a.did = b.did
WHERE b.dname IN ('Hardware','Software')
GROUP BY a.eid
HAVING COUNT(1) = 2

这只会给我们提供正好有两行的eids(即适用于软件和硬件部门)。

但是eids 还不够。我们想要有关员工的全部信息,因此我们必须包装整个查询并将其与员工表连接以获取其余信息:

SELECT a.*
FROM emp a
INNER JOIN 
(
    SELECT a.eid
    FROM works a
    INNER JOIN dept b ON a.did = b.did
    WHERE b.dname IN ('Hardware','Software')
    GROUP BY a.eid
    HAVING COUNT(1) = 2
) b ON a.eid = b.eid

你有它:在软件和硬件部门工作的员工。您可以单独执行上述每个查询,以了解我们如何得出最终解决方案的中间步骤。

【讨论】:

  • 现在我很清楚,但我不认为我会自己想出这个。虽然,随着我的进展,我可能需要其中一些技术来解决其他问题。非常感谢。
【解决方案3】:

这是查询的另一种表述:

SELECT e.*
  FROM emp AS e
  JOIN (SELECT w.eid
          FROM works AS w JOIN dept AS d
            ON d.did = w.did AND d.dname = 'Software') AS s
    ON s.eid = e.eid
  JOIN (SELECT w.eid
          FROM works AS w JOIN dept AS d
            ON d.did = w.did AND d.dname = 'Hardware') AS h
    ON h.eid = e.eid

这有两个对称的子查询,一个为软件部门生成员工 ID,一个为硬件部门生成员工 ID。选择的员工是ID在两个部门都列出的员工(因为他们都是内部联接)。

【讨论】:

  • 别名 s 和 h 为您提供 SELECT 查询结果的句柄?我发现这是最难理解的。
  • AS s 有效地将其附加到的查询结果命名为s(就好像它是一个表或视图),与AS h 及其查询类似。如果您没有被教过 JOIN 符号,那么这可能会更难,但是(IMNSHO)对学校没有教您 JOIN 符号感到羞耻。它们比旧式表示法更好的原因有很多。
猜你喜欢
  • 2020-03-03
  • 2019-01-10
  • 1970-01-01
  • 2014-01-12
  • 2010-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-03
相关资源
最近更新 更多