查询是否正确

时间:2018-06-01 14:51:53

标签: mysql sql

我有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子句之后的条件实现是否合适?

问题来自笔试,所以我没有提供任何数据集。

提前致谢!

2 个答案:

答案 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。

相关问题