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

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

Query:

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

Ответ 1

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

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

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

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

Ответ 2

Вы можете сделать

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 методов для достижения этой цели

Ответ 3

У меня нет достаточного количества очков для голосования по 2-му ответу. Но я должен не согласиться с комментариями на верхний ответ. Второй ответ:

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

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

Ответ 4

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

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

Ответ 6

Следите за подводными камнями. Если поле Name в Table1 содержит Nulls, вы попадаете в сюрпризы. Лучше:

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

Ответ 7

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

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

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

Ответ 9

Это работает для меня.

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

Ответ 10

Итак, я протестировал с базой данных более 4 миллионов записей (varchar) и вот мой результат: таблица 1 - 1,8 миллиона записей, таблица 2 - 4 миллиона записей

1) select count(*) from table1 a LEFT JOIN table2 b on a.id = b.id 
where b.id IS NULL

Took 12.68 secs

2) select count(*) from table1 a WHERE NOT EXISTS (select * from table2 b where a.id = b.id )

Took 17.11 secs

3) select count(*) from table1 
    where id NOT IN (select id from table2)

 Took over 3 minutes so i had to CTRL-C to cancel

Так что я полностью согласен с первым ответом

Ответ 11

Смотрите запрос:

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

Концептуально было бы: выборка соответствующих записей в подзапросе, а затем в основном запросе выборка записей, которые не находятся в подзапросе.

Ответ 12

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

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

И я видел синтаксис в FROM, нуждающийся в запятых между именами таблиц в mySQL, но в sqlLite казалось, что он предпочитает пробел.

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