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


469

table1 (id, ім'я)
table2 (id, ім'я)

Запит:

SELECT name   
FROM table2  
-- that are not in table1 already

Відповіді:


843
SELECT t1.name
FROM table1 t1
LEFT JOIN table2 t2 ON t2.name = t1.name
WHERE t2.name IS NULL

З : Що тут відбувається?

A : Концептуально ми вибираємо всі рядки з table1кожного ряду і намагаємося знайти рядок table2із однаковим значенням для nameстовпця. Якщо такого рядка немає, ми просто залишаємо table2частину результату порожньою для цього рядка. Тоді ми обмежуємо свій вибір, вибираючи лише ті рядки в результаті, де не відповідає відповідний рядок. Нарешті, ми ігноруємо всі поля з нашого результату, за винятком nameстовпця (з якого ми впевнені, що існує table1).

Хоча це може бути не найефективнішим можливим методом у всіх випадках, він повинен працювати в основному в кожному механізмі бази даних, який намагається реалізувати ANSI 92 SQL


16
@ z-boss: Він також найменш ефективний на SQL Server: objasnextended.com/2009/09/15/…
OMG Ponies

7
@BunkerBoy: лівий з’єднання дозволяє рядкам праворуч не існувати без того, що впливає на включення рядків зліва. Для внутрішнього з'єднання потрібні рядки зліва та праворуч. Що я тут роблю, я застосовую певну логіку, щоб отримати зворотній вибір внутрішнього з'єднання.
Kris

2
OMG це допомогло візуалізувати дуже легко, інші поставили це як 5 різних способів, але це допомогло. просто: спочатку ви отримуєте приєднатися ліворуч, все в A і все, що відповідає B, відповідає A. Але як це відбувається у лівих полях приєднання, які не приєднуються, просто нульові. Тоді ви скажете, добре, я хочу лише, що це недійсне. Таким чином, тепер у вас є всі рядки в "А", у яких не було матчу В
Мухаммед Умер

7
Слід зазначити, що це рішення (прийняте та проголосоване) є єдиним, я думаю, що це може бути відредаговано для сценарію, коли грає більше одного поля. Зокрема, я повертаю поле, поле 2, поле 3 з таблиці першої, де комбінація поля рекламного поля2 відсутня у другій таблиці. Окрім модифікації приєднання у цій відповіді, я не бачу способу зробити це з деякими іншими "ефективнішими відповідями", аргументованими нижче
TMWP

1
Просто переконайтеся, що ви використовуєте "WHERE t2.name IS NULL", а не "AND t2.name IS NULL", оскільки "і" не дасть правильних результатів. Я не розумію чому, але це факт, я перевірив це.
користувач890332

236

Можна або зробити

SELECT name
FROM table2
WHERE name NOT IN
    (SELECT name 
     FROM table1)

або

SELECT name 
FROM table2 
WHERE NOT EXISTS 
    (SELECT * 
     FROM table1 
     WHERE table1.name = table2.name)

Дивіться це запитання щодо трьох методів для цього


38
Це надзвичайно повільно при великих обсягах даних.
Лампочка1

Так, насправді це дуже повільно
sirus

Чи не повинно бути "з table1" в підзапиті не існує запиту.
Хаунд

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

Цей працював на мене .. Дякую
Thameem

81

У мене не вистачає балів повторень, щоб проголосувати другу відповідь. Але я повинен не погодитися з коментарями до верхньої відповіді. Друга відповідь:

SELECT name
FROM table2
WHERE name NOT IN
    (SELECT name 
     FROM table1)

Чи є ЗПД більш ефективним на практиці. Я не знаю чому, але я запускаю це проти 800k + записів, і різниця надзвичайна в тому, що надається другий відповідь, розміщена вище. Тільки мої 0,02 долара


30
У запиті NOT IN підзапрос виконується лише один раз, у запиті EXISTS підзапрос виконується для кожного ряду
Carrick

1
Ви дивовижні :) таким чином я перетворюю свій запит на 25 секунд, використовуючи лівий приєднання лише до 0,1 сек.
Бассем Шахін

3
відповіді не в якомусь конкретному порядку, тому друга відповідь не означає, що ви думали, що це означає.

38

Це чиста теорія множин, якої ви можете досягти за допомогою minusоперації.

select id, name from table1
minus
select id, name from table2

Як ви вважаєте, це набагато ефективніше, ніж лівий приєднатися?
uhs

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

9
У T-SQL оператор набору є "крім". Це дуже зручно для мене і не спричинило уповільнення.

2
У SQLite оператор "мінус" також є "крім".
lifjoy

MySQL не підтримує оператора MINUS.
Мухаммед Азеем


16

Слідкуйте за підводними каменями. Якщо поле Nameв Table1містить NULLS ви в сюрпризи. Краще:

SELECT name
FROM table2
WHERE name NOT IN
    (SELECT ISNULL(name ,'')
     FROM table1)

1
COALESCE> ISNULL (ISNULL - марний додаток T-SQL до мови, який не робить нічого нового чи кращого, ніж COALESCE)
Кріс,

14

Ось що найкраще працювало для мене.

SELECT *
FROM @T1
EXCEPT
SELECT a.*
FROM @T1 a
JOIN @T2 b ON a.ID = b.ID

Це було вдвічі швидше, ніж будь-який інший метод, який я спробував.


Дякую, це добре працює і з великою кількістю даних! Але мені просто цікаво термін "За винятком".
PatsonLeaner


7

Ця робота гостра для мене

SELECT * 
FROM [dbo].[table1] t1
LEFT JOIN [dbo].[table2] t2 ON t1.[t1_ID] = t2.[t2_ID]
WHERE t2.[t2_ID] IS NULL

1

Переглянути запит:

SELECT * FROM Table1 WHERE
id NOT IN (SELECT 
        e.id
    FROM
        Table1 e
            INNER JOIN
        Table2 s ON e.id = s.id);

Концептуально було б: Вибір відповідних записів у підзапиті, а потім у головному запиті, що отримує записи, які не є в підзапиті.


0

Я збираюся репостувати (оскільки я ще недостатньо крутий, щоб коментувати) правильну відповідь .... на випадок, якщо хтось інший подумав, що це потрібно краще пояснити.

SELECT temp_table_1.name
FROM original_table_1 temp_table_1
LEFT JOIN original_table_2 temp_table_2 ON temp_table_2.name = temp_table_1.name
WHERE temp_table_2.name IS NULL

І я бачив синтаксис ВІД, коли потрібні коми між іменами таблиць у mySQL, але в sqlLite, здавалося, він віддає перевагу пробілу.

Підсумок - коли ви використовуєте неправильні назви змінних, це залишає питання. Мої змінні повинні мати більше сенсу. І хтось повинен пояснити, чому нам потрібна кома чи ні.


0

Якщо ви хочете вибрати конкретного користувача

SELECT tent_nmr FROM Statio_Tentative_Mstr
WHERE tent_npk = '90009'
AND
tent_nmr NOT IN (SELECT permintaan_tent FROM Statio_Permintaan_Mstr)

Це tent_npkпервинний ключ користувача

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