Является ли запрос правильным - PullRequest
0 голосов
/ 01 июня 2018

У меня есть 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 голосов
/ 01 июня 2018

Да, условия в предложении WHERE кажутся действительными.

Существует множество определений таблиц, но мы не видим никакого определения таблицы Works_on.Я ожидаю, что на самом деле это была ссылка на таблицу 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
0 голосов
/ 01 июня 2018

Вы можете просто использовать IN.

     SELECT * FROM Employee JOIN timesheet
  ON  Employee.Empno = timesheet.Empno 
  WHERE Pnumber in( 30,40,50)

Так как это экзамен, они иногда делают слова или любой проект или должны быть всем проектом.Мой ответ для всех участников проекта.

Если это позже, вам нужно использовать AND.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...