Як виключити рядки, які не поєднуються з іншою таблицею?


86

У мене є дві таблиці, в одній є первинний ключ, у іншої - зовнішній ключ.

Я хочу отримати дані з первинної таблиці, лише якщо у вторинній таблиці немає запису, що містить її ключ. Сортування як протилежність простого внутрішнього об'єднання, яке повертає лише рядки, які з'єднуються за допомогою цього ключа.

Відповіді:


269

текст заміщення

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

Повне зображення об’єднання текст заміщення

З aticle: http://www.codeproject.com/KB/database/Visual_SQL_Joins.aspx


9
нарешті! чому їх немає в підручниках і чому їх у моїх викладачів в університеті не було ?! вони використовували найгірші можливі пояснення у світі, далеко не наближені до них!
pythonian29033

4
Це золото. Ненавиджу писати коментар, який не має змісту, крім виразних похвал, але давай! Це чудова відповідь. Дякую, @Pranay Rana.
0xbe5077,

1
Поясніть, будь ласка, чому, B.Key IS NULLале ми все одно порівнянні A.Key = B.Key?
Do Nhu Vy

1
@DoNhuVy просто, порівняння відбувається в реченні "ON", в LEFT або RIGHT приєднанні, якщо немає відповідного рядка, тоді приєднується рядок з усіма NULL, після чого ви перевіряєте IS NULL, щоб знати, що немає відповідного рядка . (Це, до речі, працює лише в тому випадку, якщо тестоване поле НЕ НУЛЕВО, тобто не може мати НУЛЬ з якихось інших причин)
Григорій Магаршак,

Я використовую нижченаведений запит: ВИБЕРІТЬ А. * З #PurgeFilesListNew ПОВНЕ ВНЕШНЄ ПРИЄДНАННЯ #DoNotPurgeFilesListNew B НА A.JobFileId = B.JobFileId І A.AccountID = B.AccountID, де A.AccountID IS NULL OR 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


ну, він не публікував те, що використовується СУБД, однак у MySql LEFT JOINперевершуєNOT EXIST
The Scrum Meister

@ Scrum Meister: я сказав швидше? Шукайте IN проти EXISTS vs JOIN, щоб виявити смислові та логічні відмінності ...
gbn

@gbn Вибачте, я думав, під "кращим вибором" ви мали на увазі швидше. Чи можете ви тоді пояснити, яким чином це кращий вибір? objasnixtended.com/2009/09/18/…
Scrum Meister

1
@ The Scrum Meister: як правило, будь-якому РЕЄСТРУВАННЮ може знадобитися ВИЗНАЧЕННЯ. NOT IN із нулем у списку дає значення false. IN / EXISTS поводяться однаково. Однак, єдиною "безпечною" конструкцією є (НЕ) ІСНУЄ, якщо вам не подобається непослідовність
gbn


4

використовуйте ліве приєднання "не існує":

SELECT p.*
FROM primary_table p LEFT JOIN second s ON p.ID = s.ID
WHERE s.ID IS NULL


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 хвилин.

Для тих, хто шукає рішення "NOT IN" у Cognos, ось що я зробив. Створіть запит, який об’єднує таблиці A і B за допомогою LEFT JOIN у Cognos, вибравши тип посилання: таблиця A. Ключ має значення "від 0 до N" у таблиці B, а потім додав фільтр (вони відповідають реченням Where) для: таблиці B .Ключ NULL.

Біг швидко і як оберіг.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.