我有6个表(SQL Fiddle):
CREATE TABLE Department(
Dname varchar(10),
Dnumber int(5),
Mgrno int(5),
PRIMARY KEY(Dnumber)
);
CREATE TABLE Employee(
Fname varchar(20),
Lname varchar(20),
Empno int(5),
Bdate date,
Address varchar(10),
Salary float(5),
Dnumber int(5),
PRIMARY KEY(Empno),
FOREIGN KEY(Dnumber) REFERENCES Department(Dnumber)
);
CREATE TABLE Location(
Dnumber int(5),
Dlocation varchar(10),
PRIMARY KEY(Dlocation),
FOREIGN KEY(Dnumber) REFERENCES Department(Dnumber)
);
CREATE TABLE Project(
Pname varchar(10),
Pnumber int(5),
Location varchar(10),
Dnumber int(5),
PRIMARY KEY(Pnumber),
FOREIGN KEY(Dnumber) REFERENCES Department(Dnumber)
);
CREATE TABLE Timesheet(
Empno int(5),
Pnumber int(5),
Hours_per_day int(5),
FOREIGN KEY(Empno) REFERENCES Employee(Empno),
FOREIGN KEY(Pnumber) REFERENCES Project(Pnumber)
);
CREATE TABLE Dependent(
Empno int(5),
Dependent_name varchar(10),
DOB date,
Sex varchar(5),
Relationship varchar(10),
FOREIGN KEY(Empno) REFERENCES Employee(Empno)
);
我被要求编写一个查询来检索所有从事项目编号为30,40,50的员工的详细信息
这是我的尝试:
SELECT * FROM Employee JOIN Timesheet
ON Employee.Empno = Timesheet.Empno
WHERE (Pnumber = 30 OR Pnumber = 40 OR Pnumber = 50)
我在WHERE子句之后的条件实现是否合适?
问题来自笔试,所以我没有提供任何数据集。
提前致谢!
答案 0 :(得分:4)
是的,WHERE
子句中的条件似乎有效。
有很多表定义,但我们没有看到Works_on
表的任何定义。我希望这实际上是对Timesheet
表的引用。
请注意,join操作将导致为员工返回多行;此查询将返回Timesheet中每个匹配行的Employee行。
我建议限定所有列引用,即使它们在语句中没有歧义。这有助于未来的读者,并且当相同名称的列被添加到另一个表时,也可以防止查询中断。
另外,我建议抛弃SELECT列表中的*
,并明确列出要返回的列。或者,如果我们必须使用*
来返回所有列,请使用表名(或表别名)限定该列。
如上所述,查询将返回已在任何一个项目上工作的员工列表。这是一个从事项目30和40但尚未参与项目50的员工,将被包括在内。
该要求的另一种解释是只返回那些参与了所有三个项目的员工。该结果将需要不同的查询。
这是满足该规范的一种(相当长的啰嗦)可能的方法:
SELECT e.*
FROM Employee e
WHERE EXISTS ( SELECT 1
FROM Timesheet t1
WHERE t1.empno = e.empno
AND t1.pnumber = 30
)
AND EXISTS ( SELECT 1
FROM Timesheet t2
WHERE t2.empno = e.empno
AND t2.pnumber = 40
)
AND EXISTS ( SELECT 1
FROM Timesheet t3
WHERE t3.empno = e.empno
AND t3.pnumber = 50
)
还有其他查询模式也符合规范。
例如,在HAVING子句中使用聚合表达式......
SELECT e.*
FROM ( SELECT t.empno
FROM Timesheet t
WHERE t.pnumber in (30,40,50)
GROUP
BY t.empno
HAVING COUNT(DISTINCT t.pnumber) = 3
) q
JOIN Employee e
ON e.empno = q.empno
ORDER
BY e.empno
或者,正如@MKhalidJunaid建议的那样,我们可以使用条件聚合......
SELECT e.*
FROM ( SELECT t.empno
FROM Timesheet t
GROUP
BY t.empno
HAVING MAX(IF( t.pnumber = 30 ,1,0))
AND MAX(IF( t.pnumber = 40 ,1,0))
AND MAX(IF( t.pnumber = 50 ,1,0))
) q
JOIN Employee e
ON e.empno = q.empno
ORDER
BY e.empno
答案 1 :(得分:1)
你可以简单地使用IN。
SELECT * FROM Employee JOIN timesheet
ON Employee.Empno = timesheet.Empno
WHERE Pnumber in( 30,40,50)
从考试开始,他们有时会做单词和任何项目的伎俩,或者必须是所有项目。我的答案是任何一个项目。
如果是以后,则需要使用AND。