SQL для поиска записей, у которых нет типа записи в другой таблице

#sql #sql-server #sql-server-2008

#sql #sql-сервер #sql-server-2008

Вопрос:

Я пытаюсь написать некоторый SQL, который запрашивает две таблицы и возвращает записи, у которых нет определенного типа записи в другой таблице.

Если таблица 1 является таблицей employee, в которой есть EmpID, имя, фамилия.

и 2-я таблица — это таблица бронирований, в которой есть идентификатор бронирования, EmpID, год

Я хочу найти все записи, в которых нет бронирований на 2014 год.

итак, если таблица employee является:

 EMPID   Name   Surname

1        John   Doe
2        Bob    Smith
  

и таблица резервирования

 Booking ID   Emp ID   Year
1             1        2013
2             1        2014
3             2        2012
4             2        2013
  

Я хочу, чтобы sql только

Комментарии:

1. Как всегда, спасибо за вашу помощь!! как только я опубликовал его и вернулся к SQL Manager, я понял, что я был глуп и запрашивал идентификатор бронирования, когда я хочу удалить все идентификаторы сотрудников, а не идентификаторы бронирования!! Спасибо!!!

2. @Abraham @Comments — лучший способ.

Ответ №1:

  SELECT * FROM employee
 LEFT JOIN Booking ON Booking.empid = employee.empid AND year = 2014
 WHERE Booking.empid IS NULL
  

Ответ №2:

Добавьте WHERE предложение с NOT EXISTS проверкой для фильтрации требуемых записей:

 SELECT e.EMPID, e.[Name], e.Surname
FROM Employee e
WHERE NOT EXISTS 
      (SELECT EmpID 
       FROM Booking b 
       WHERE b.BookingId = e.EmpId and b.Year = 2014)
  

Пример скрипта SQL

Для справки, вот сценарий создания / вставки SQL Fiddle:

 create table employee(EMPID int, Name varchar(50), Surname varchar(50))
create table booking(BookingID int, EmpID int, Year int)

insert into employee (EMPID, Name, Surname) values(1,'John','Doe')
insert into employee (EMPID, Name, Surname) values(2,'Bob','Smith')

insert into booking(BookingID,EmpID,Year) values(1,1,2013)
insert into booking(BookingID,EmpID,Year) values(2,1,2014)
insert into booking(BookingID,EmpID,Year) values(3,2,2012)
insert into booking(BookingID,EmpID,Year) values(4,2,2013)
  

Комментарии:

1. Это не сработает. Он хочет сделать противоположное тому, что будет делать внутреннее соединение.

2. Способ включения скрипта SQL. Это здорово.

Ответ №3:

Одним из часто просматриваемых решений является EXCEPT. Это специфичный синтаксис SQL Server, который в основном противоположен ОБЪЕДИНЕНИЮ

 SELECT 
       e.EMPID,
       e.Name,
       e.Surname
FROM
      employee e
EXCEPT
SELECT 
       e.EMPID,
       e.Name,
       e.Surname
FROM
      employee e 
      INNER JOIN Booking B
      ON e.empID = b.empid
WHERE
       b.year = 2014
  

ДЕМОНСТРАЦИЯ

Другой, также упущенный из виду синтаксис — это != ANY основное различие между этим и НЕ В том, что вам не нужно беспокоиться о нулевом EmpID при бронировании

 SELECT 
       EmpId, Name 
FROM   employee e
WHERE  empid != ANY (SELECT empid 
                     FROM   booking 
                     WHERE  year = 2014) 
  

ДЕМОНСТРАЦИЯ

Комментарии:

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

Ответ №4:

  select * from employee
   where empid not in
   (select empid from Booking
        where year = 2014)
  

Конечно, только для иллюстрации, «выбрать *» обычно не очень хорошо, лучше возвращать столбцы, которые вы конкретно хотите…

Однако, если ваша таблица бронирования содержит пустые идентификаторы, вы можете обработать ее чем-то вроде этого:

 select * from employee
   where empid not in
   (select empid from Booking
        where year = 2014 and empid is not null)
  

Комментарии:

1. Что касается вашей заметки, вы можете захотеть взглянуть на этот вопрос на meta.se для возможных альтернатив

2. @Анон, вы ввели нулевой empid в таблицу резервирования, чтобы вызвать сбой. Это не было указано в сценарии OPs. Тем не менее, в интересах полноты я обновил свой ответ, чтобы рассмотреть и это.

3. @ConradFrix — спасибо, я не знал об этой странице, интересно посмотреть дебаты. То, как я это прочитал, я думаю, что я в порядке, принятый ответ предполагает, что уместно предложить OP заменить звездочку соответствующими полями? Конечно, когда я имею дело со своими ассистентами, я бы предпочел слегка подтолкнуть их к подобным вещам, чтобы побудить их подумать об этом самостоятельно. Оцените ссылку и обратите внимание.

4. @PulseLab решения, которые легко ломаются или имеют неожиданные побочные эффекты, являются плохими решениями. Существуют надежные альтернативы ( NOT EXISTS , LEFT JOIN , EXCEPT )

5. @PulseLab то, что у вас было абсолютно нормально, и я не хотел предлагать иное. Также я бы написал, where year = 2014 and empid is not null а не isnull просто чтобы избежать возможности того, что кто-то умничает и использует -1 в качестве фактического empid