Как исключить строки, которые не присоединяются к другой таблице?

86

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

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

Хаддей
источник

Ответы:

269

альтернативный текст

SELECT <select_list> 
FROM Table_A A
LEFT JOIN Table_B B
ON A.Key = B.Key
WHERE B.Key IS NULL

Полное изображение присоединения альтернативный текст

Из статьи: http://www.codeproject.com/KB/database/Visual_SQL_Joins.aspx

Праная Рана
источник
9
наконец-то! почему их нет в учебниках и почему у моих преподавателей в университете их не было ?! они использовали худшие из возможных объяснений в мире, даже близко не близкие к этим!
pythonian29033
4
Это золото. Ненавижу писать комментарий, в котором нет содержания, кроме бурной похвалы, но давай! Это отличный ответ. Спасибо, @Pranay Rana.
0xbe5077ed 06
1
Пожалуйста, объясните мне, почему B.Key IS NULLмы все еще сопоставимы A.Key = B.Key?
Do Nhu Vy
1
@DoNhuVy просто, сравнение выполняется в предложении "ON", в соединении LEFT или RIGHT, если нет соответствующей строки, тогда присоединяется строка со всеми NULL, после чего вы проверяете IS NULL, чтобы узнать, что нет соответствующей строки . (Это, кстати, работает только в том случае, если поле, которое вы тестируете, НЕ НУЛЕВО, т.е. не может иметь НУЛЬ по какой-то другой причине)
Грегори Магаршак
Я использую следующий запрос: SELECT A. * FROM #PurgeFilesListNew A FULL OUTER JOIN #DoNotPurgeFilesListNew B ON A.JobFileId = B.JobFileId AND A.AccountID = B.AccountID, ГДЕ A.JobFileId IS NULL ИЛИ B.JobFileId IS NULL A.AccountID IS NULL ИЛИ B.AccountID IS NULL В принципе, у меня есть два сравнения двух значений в предложении «ON». Он работает нормально, но запрос возвращает пустую строку для тех строк, которые не совпадают. Как это решить? Пожалуйста, помогите
HarshSharma
10
SELECT
   *
FROM
   primarytable P
WHERE
   NOT EXISTS (SELECT * FROM secondarytable S
     WHERE
         P.PKCol = S.FKCol)

Как правило , (NOT) EXISTSэто лучший выбор (NOT) INили(LEFT) JOIN

gbn
источник
ну, он не опубликовал, какая СУБД используется, однако в MySql LEFT JOINпревосходитNOT EXIST
The Scrum Meister
@The Scrum Meister: я сказал быстрее? Найдите IN vs EXISTS vs JOIN, чтобы обнаружить семантические и логические различия ...
gbn
@gbn Извините, я подумал, что под "лучшим выбором" вы имели в виду быстрее. Не могли бы вы тогда объяснить, каким образом это лучший выбор? объяснятьextended.com
2009/
1
@ The Scrum Meister: как правило, для любого типа JOIN может потребоваться DISTINCT. NOT IN с нулевым значением в списке дает false. IN / EXISTS ведут себя так же. Однако единственная «безопасная» конструкция (НЕ) СУЩЕСТВУЕТ, если вам не нравится непоследовательность
gbn
@ The Scrum Meister: объяснениеextended.com /
2009/06/16/in-vs-join-vs-exists
4

используйте левое соединение "не существует":

SELECT p.*
FROM primary_table p LEFT JOIN second s ON p.ID = s.ID
WHERE s.ID IS NULL
Скрам Мейстер
источник
4

Другое решение:

SELECT * FROM TABLE1 WHERE id NOT IN (SELECT id FROM TABLE2)
Али Акбар
источник
3
SELECT P.*
FROM primary_table P
LEFT JOIN secondary_table S on P.id = S.p_id
WHERE S.p_id IS NULL
Томми
источник
2
Есть вопрос ... если мы используем условие, P.key = S.keyа затем говорим where S.key IS NULL, то разве это не делает P.key также нулевым?
Somjit
2

Если вы хотите выбрать столбцы из «Первой таблицы», которые также присутствуют во Второй таблице, то в этом случае вы также можете использовать EXCEPT. В этом случае имена столбцов также могут быть разными, но тип данных должен быть таким же.

Пример:

select ID, FName
from FirstTable
EXCEPT
select ID, SName
from SecondTable
Анил Соман
источник
0

Это было полезно использовать в COGNOS, потому что создание оператора SQL «Not in» в Cognos было разрешено, но его выполнение заняло слишком много времени. Я вручную закодировал таблицу A для присоединения к таблице B в Cognos как A.key «не в» B.key, но запрос занимал слишком много времени / не возвращал результаты через 5 минут.

Для всех, кто ищет решение «НЕ ВХОДИТ» в Cognos, вот что я сделал. Создайте запрос, который объединяет таблицы A и B с LEFT JOIN в Cognos, выбрав тип ссылки: таблица A. Key имеет значения от «0 до N» в таблице B, затем добавлен фильтр (они соответствуют предложениям Where) для: table B .Key имеет значение NULL.

Бежал быстро и как шарм.

JennyB
источник