我写了这个查询,以获取员工的名字和姓氏,以及从5号工作的ProtectX工作超过10小时的员工的工作时间。
select distinct fname, lname, hours
from Project
left join Employee on dnum = dno
left join Works_On on pnumber = pno
where dno = 5 and hours > 10 and pname = 'ProductX' group by fname;
但我的结果没有任何意义。
+----------+---------+-------+
| fname | lname | hours |
+----------+---------+-------+
| Franklin | Wong | 32.50 |
| John | Smith | 32.50 |
| Joyce | English | 32.50 |
| Ramesh | Narayan | 32.50 |
+----------+---------+-------+
首先,富兰克林甚至没有使用ProjectX。如果我删除dno = 5完全没有意义,我会得到完全相同的结果。如果我删除pname = ProjectX也一样。如果他没有与where子句对齐,为什么地球上有富兰克林呢?而且,小时数是一样的是什么?这个数字只应该显示给约翰史密斯,但它会显示给所有人?
答案 0 :(得分:1)
这应该有效:
select distinct p.fname, p.lname, w.hours
from Project p
join Employee e on p.dnum = e.dno
join Works_On w on p.pnumber = w.pno
and w.essn = e.ssn
where e.dno = 5 and w.hours > 10 and p.pname = 'ProductX' group by fname;
正如在私人聊天中所讨论的,表的主键分别是:
Project
:pnumber
Employee
:SSN
Works_on
:pno
和essn
您的查询是将works_on
表与project
表相关联,但缺少与employee
表(w.essn = e.ssn
)的关系。
这些密钥(pno
和essn
)都需要确保正确关联Employee
/ Project
/ Work_on
。
如您所见,我删除了left join
。当您想要返回左表中的所有行时,即使右表中存在关联的行,这些也很有用。
以示例:即使他们没有在ProjectX上工作,我也想要所有员工的列表。
在您的情况下,这不是必需的,因为您只想要参与项目的员工。
另一个常见的例子是,如果您想要没有在项目X上工作的所有员工的列表。
最后,我看到项目引用直接在employee表中(字段DNO
)。这意味着员工可以同时参与一个项目。
如果您希望您的员工能够同时参与许多项目,您需要从员工表中删除项目参考,并将其放在关联表中,如下所示(该脚本缺少字段的正确数据类型;它们必须与它们引用的表格完全相同:
CREATE TABLE project_employee (
SSN VARCHAR(10) NOT NULL,
pnumber SMALLINT(5) NOT NULL,
PRIMARY KEY (id, pnumber),
FOREIGN KEY (SSN) REFERENCES Employee (SSN)
ON DELETE CASCADE
ON UPDATE RESTRICT,
FOREIGN KEY (pnumber) REFERENCES Project (SSN)
ON DELETE CASCADE
ON UPDATE RESTRICT
);
您可以使用以下查询填充此表(当然,我无法为您测试):
INSERT INTO project_employee (
SSN,
pnumber
)
SELECT
SSN,
DNO
FROM Employee
答案 1 :(得分:0)
您选择Project
中的所有行,无论其pno
如何。由于(我猜)pname
是Work_on
表的一列,它会筛选出left join
- ed的部分,但不会筛选出您正在选择的主表。< / p>
只需过滤pno
列(如果这是Projects
列)。