Выбор ВСЕХ из определенного диапазона - PullRequest
0 голосов
/ 03 мая 2018

У меня следующий вопрос:

Найдите имена сотрудников, которые работают на всех проектах, контролируемых отдел № 5.

У меня есть следующие таблицы: Сотрудники (SSN), Works_On (SSN, PNumber), Проекты (PNumber, DNumber).

Я пытаюсь выяснить "ВСЕ". Я пробовал разные методы, но я пытаюсь создать каноническое дерево запросов, поэтому мне нужно убедиться, что SQL-запрос может быть преобразован в него.

Я пробовал следующее:

SELECT E.Fname, E.Lname
FROM Employee AS E, works_on AS W
WHERE E.SSN IN ALL
(
SELECT SSN
FROM Projects AS P
WHERE W.SSN = E.SSN AND W.PNUMBER = P.PNUMBER AND P.DNUMBER = 5
);

Но я не уверен, что это сработает, так как я использовал IN ALL. Еще одна вещь, которую я попробовал, это подсчитать количество работ и групп по сотрудникам и подсчитать количество проектов.

В конце концов я нашел это:

select fname, lname
from employee
where not exists ( (select pnumber from project where dnum = 5)
                   MINUS 
                   (select pno from works_on where essn = ssn)
                 );

Но я не смог превратить его в дерево.

Есть ли у вас какие-либо предложения, которые я мог бы использовать? И да, это домашнее задание.

Ответы [ 2 ]

0 голосов
/ 03 мая 2018

Я думаю group_concat() - самое простое решение. Если нет дубликатов, вы можете получить все проекты для отдела 5:

select group_concat(p.pnumber order by p.pnumber)
from projects p
where dnumber = 5;

Затем вы можете сделать то же самое для сотрудников и сопоставить их:

select e.ssn, group_concat(wo.pnumber order by wo.pnumber)
from works_on wo
where wo.pnumber in (select p.pnumber from projects p where p.dnumber = 5)
group by e.ssn;

И, наконец, сопоставьте два, например, в предложении having:

select e.ssn, group_concat(wo.pnumber order by wo.pnumber) as projects
from works_on wo
where wo.pnumber in (select p.pnumber from projects p where p.dnumber = 5)
group by e.ssn
having projects = (select group_concat(p.pnumber order by p.pnumber)
                   from projects p
                   where dnumber = 5
                  );

Другой подход, использующий реляционную логику, будет выглядеть так:

select e.ssn
from employees e cross join
     projects p left join
     works_on wo
     on e.ssn = wo.ssn and p.pnumber = wo.pnumber
where p.dnumber = 5
group by e.ssn
having count(wo.snn) = count(*);   -- no NULL values
0 голосов
/ 03 мая 2018
DROP TABLE IF EXISTS employees;

CREATE TABLE employees (employee_id SERIAL PRIMARY KEY);

DROP TABLE IF EXISTS employee_project;

CREATE TABLE employee_project (employee_id INT NOT NULL, project_id INT NOT NULL,PRIMARY KEY(employee_id,project_id));

DROP TABLE IF EXISTS projects;

CREATE TABLE projects(project_id SERIAL PRIMARY KEY, department_id INT NOT NULL);

INSERT INTO employees VALUES (101),(102),(103);

INSERT INTO employee_project VALUES (101,5004),(101,5005),(101,5006),(101,5007),(102,5004),(102,5007),(102,5008),(103,5006),(103,5007),(103,5008);

INSERT INTO projects VALUES (5004,1),(5005,2),(5006,5),(5007,5),(5008,4),(5009,3);

Consider the following:

SELECT * 
  FROM employees e 
  JOIN projects p 
  LEFT 
  JOIN employee_project ep 
    ON ep.employee_id = e.employee_id 
   AND ep.project_id = p.project_id 
 WHERE p.department_id = 5;
+-------------+------------+---------------+-------------+------------+
| employee_id | project_id | department_id | employee_id | project_id |
+-------------+------------+---------------+-------------+------------+
|         101 |       5006 |             5 |         101 |       5006 |
|         102 |       5006 |             5 |        NULL |       NULL |
|         103 |       5006 |             5 |         103 |       5006 |
|         101 |       5007 |             5 |         101 |       5007 |
|         102 |       5007 |             5 |         102 |       5007 |
|         103 |       5007 |             5 |         103 |       5007 |
+-------------+------------+---------------+-------------+------------+

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

  1. Количество отдельных проектов в результате равно количеству отдельных проектов, перечисленных вместе с пользователями 101 и 103 (то есть, сколько раз эти числа появляются в столбце 4).
  2. Пользователь 102 имеет нулевой результат, что означает, что он не участвует во всех проектах этого отдела.
...