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

table1 (id, name)
table2 (id, name)

запрос:

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

9 ответов


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

Q: что здесь происходит?

A: по существу, мы выбираем все строки из table1 и для каждой строки мы пытаемся найти строку table2 С тем же значением для . Если такой строки Нет, мы просто оставляем table2 часть нашего результата пуста для этой строки. Затем мы ограничиваем наш выбор, Выбирая только те строки в результате, где соответствующая строка не существует. Наконец, мы игнорируем все поля из нашего результата за исключением name столбец (тот, который мы уверены, что существует, от table1).

хотя это может быть не самый эффективный метод во всех случаях, он должен работать в основном в каждом ядре базы данных, когда-либо пытающемся реализовать ANSI 92 SQL


можно сделать

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)

посмотреть этот вопрос для 3 методов для достижения этого


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

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

гораздо эффективнее на практике. Я не знаю, почему, но я запускаю его против 800k+ records, и разница огромна с преимуществом, предоставленным 2-му ответу, опубликованному выше. Просто мои 0.02$


это чистая теория множеств, которую вы можете достичь с помощью minus операции.

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

остерегайтесь ловушек. Если поле Name на Table1 содержат нули вы находитесь в для сюрпризов. Лучше будет:

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

можно использовать EXCEPT в mssql или MINUS в oracle они идентичны в соответствии с:

http://blog.sqlauthority.com/2008/08/07/sql-server-except-clause-in-sql-server-is-similar-to-minus-clause-in-oracle/


вот что сработало лучше всего для меня.

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

Это было более чем в два раза быстрее, чем любой другой метод, который я пробовал.


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

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

Я собираюсь перепостить (так как я еще не достаточно крут, чтобы комментировать) в правильном ответе....на случай, если кто-то еще посчитает, что это нуждается в объяснении.

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 он, казалось, предпочитал пространство.

нижняя строка, когда вы используете плохие имена переменных, оставляет вопросы. Мои переменные должны иметь больше смысла. И кто-то должен объяснить, зачем нам запятая или нет.