SQL: выберите группы, которые не содержат определенного значения - PullRequest
0 голосов
/ 28 апреля 2018

Я использую Microsoft SQL Server Management Studio 2014, и у меня есть эти 3 таблицы:

СОТРУДНИКИ

EMPID | FIRSTNAME
  1   | JOHNNY
  2   | DWAYNE
  3   | TOM
  4   | CHRISTIAN
  5   | JACK
  6   | BRAD
  7   | ADAM
  8   | MATT
  9   | WILL
  10  | JIM

САМОЛЕТЫ

AID | NAME
 1  | BOEING 1
 2  | BOEING 2
 3  | BOEING 3
 4  | BOEING 4
 5  | AIRBUS 1
 6  | AIRBUS 2
 7  | LEARJET
 8  | DOUGLAS
 9  | JUMBO
 10 | ILYUSHIN

CERTIFIED

EMPID | AID
  1   |  1
  1   |  2
  1   |  3
  1   |  4
  4   |  2
  4   |  3
  7   |  1
  7   |  2
  7   |  5
  7   |  6
  8   |  7
  8   |  8
  8   |  9
  2   |  10
  2   |  1
  2   |  9
  3   |  10
  5   |  8
  5   |  9

Концепция состоит в том, что в штате 10 сотрудников и 10 самолетов. Таблица CERTIFIED определяет, какой сотрудник имеет право пилотировать какие самолеты. Хотя не все сотрудники являются пилотами. Что мне нужно, так это каким-то образом выбрать всех пилотов, которые не сертифицированы для использования Боинга. То, что я пытался, но не работало, это следующее:

SELECT DISTINCT FIRSTNAME
FROM EMPLOYEES
WHERE EMPID IN (SELECT EMPID
                FROM CERTIFIED
                WHERE AID NOT IN (SELECT AID FROM AIRCRAFTS WHERE NAME LIKE 'BOEING%'))

Что дает эти результаты:

JACK
MATT
TOM
ADAM
DWAYNE

Это неправильно, поскольку согласно СЕРТИФИЦИРОВАННОЙ таблице ADAM и DWAYNE имеют право пилотировать хотя бы один Боинг.

Буду признателен за любую помощь, заранее спасибо!

Ответы [ 3 ]

0 голосов
/ 28 апреля 2018

Вы должны использовать NOT IN emp, сертифицированные Boeing, в соединении с самолетами

SELECT DISTINCT FIRSTNAME
FROM EMPLOYEES
WHERE EMPID NOT IN (SELECT EMPID
                FROM CERTIFIED c 
                INNER JOIN AIRCRAFTS a ON on a.AID  = c.AID 
                WHERE a.NAME LIKE 'BOEING%')
0 голосов
/ 28 апреля 2018

Попробуйте этот запрос ...

SELECT employees.empid, Max(employees.firstname) AS FirstName 
FROM   certified 
       INNER JOIN employees ON employees.empid = certified.empid 
WHERE  certified.empid NOT IN (SELECT certified.empid 
                               FROM   certified 
                               INNER JOIN aircrafts ON aircrafts.aid = certified.aid 
                               WHERE  aircrafts.NAME LIKE 'BOEING%') 
GROUP  BY employees.empid 

Демо: http://www.sqlfiddle.com/#!18/8f26d/27/0

Результат

+-------+-----------+
| EMPID | FirstName |
+-------+-----------+
|     3 | TOM       |
|     5 | JACK      |
|     8 | MATT      |
+-------+-----------+
0 голосов
/ 28 апреля 2018

Я думаю, что ваш запрос дает любому сотруднику, который сертифицирован на самолете не Boeing - немного другой набор людей.

На ваш вопрос я бы пошел на not exists:

select e.*
from employees e
where not exists (select 1
                  from certified c join
                       aircrafts a
                       on c.aid = a.aid
                  where e.empid = c.empid and a.name like '%BOEING%'
                 );

Другой подход - если вы просто хотите идентификатор сотрудника - использует агрегацию и having

select e.empid, e.firstname
from employees e join
     certified c
     on e.empid = c.empid join
     aircrafts a
     on c.aid = a.aid
group by e.empid, e.firstname
having sum(case when a.name like '%BOEING%' then 1 else 0 end) = 0;

Мне нравится этот метод, потому что он очень легко обобщает другие условия - такие как мухи Боинг, но не Аэробус или мухи Learjet и Cessna.

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