Справка по выбору соединения SQL - PullRequest
2 голосов
/ 15 мая 2009

У меня проблемы с определением запроса для этого сценария. У меня есть две таблицы, которые я хочу использовать в этом запросе, они выглядят так:

Units
  ID
  Other Data
People
  ID
  UnitID  <-- fk to Units
  Other Data

Вот что я хочу сделать:
Я хочу выбрать все единицы, которые НЕ имеют строки в таблице People, связанной с ними. Как я могу это сделать?

Ответы [ 5 ]

8 голосов
/ 15 мая 2009
SELECT Units.* FROM Units LEFT JOIN People ON People.UnitID = Units.ID WHERE People.ID IS NULL

или альтернативно

SELECT Units.* FROM Units WHERE NOT EXISTS (SELECT 1 FROM People WHERE People.UnitID = Units.ID)

или даже

SELECT Units.* FROM Units WHERE Units.ID NOT IN (SELECT UnitID FROM People)
3 голосов
/ 15 мая 2009
SELECT * FROM Units  
WHERE NOT EXISTS  
(SELECT * FROM People WHERE UnitID = Units.ID)
2 голосов
/ 15 мая 2009
SELECT * FROM Units
WHERE ID NOT IN (SELECT UnitID FROM People)
1 голос
/ 16 мая 2009
SELECT U.*
FROM Units U
WHERE NOT EXISTS (
   SELECT 1
   FROM People P
   WHERE U.ID = P.UnitID
)

Обратите внимание, что это называется (анти) полусоединением. Это фактическое соединение, а не коррелированный подзапрос.

Другой обычно используемый метод:

SELECT U.*
FROM
   Units U
   LEFT JOIN People P ON U.ID = P.UnitID
WHERE
   P.UnitID IS NULL

Обратите внимание, что в предложении объединения должны быть указаны дополнительные критерии для объединения (скажем, вы хотите присоединиться только к тем, кто был активен). Сказать "1007 *.

" не получится

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

Примечание: использование «SELECT 1» в полусоединениях вместо «SELECT *» сэкономит некоторые циклы во время компиляции запроса, поскольку * фактически расширяется до списка столбцов, а затем удаляется.

1 голос
/ 15 мая 2009

Вы можете использовать not in (выбрать ...)

SELECT ID
FROM Units
WHERE ID NOT IN (SELECT UnitID FROM People);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...