Ответ 1
Попробуйте это
SELECT ID, Name
FROM Table1
WHERE ID NOT IN (SELECT ID FROM Table2)
У меня есть две таблицы с обязательным первичным ключом в базе данных, и я хочу найти между ними непересекающийся набор. Например,
Table1
имеет столбцы (ID, Name
) и примеры данных: (1 ,John), (2, Peter), (3, Mary)
Table2
имеет столбцы (ID, Address
) и данные образца: (1, address2), (2, address2)
Итак, как мне создать SQL-запрос, поэтому я могу получить строку с идентификатором из Table1
, которая не находится в Table2
. В этом случае следует вернуть (3, Mary)
?
Ps. Идентификатор является основным ключом для этих двух таблиц.
Спасибо заранее.
Попробуйте это
SELECT ID, Name
FROM Table1
WHERE ID NOT IN (SELECT ID FROM Table2)
Используйте LEFT JOIN
SELECT a.*
FROM table1 a
LEFT JOIN table2 b
on a.ID = b.ID
WHERE b.id IS NULL
Я провел несколько тестов (на Postgres 9.5), используя две таблицы с ~ 2M строк в каждой. Этот запрос ниже по крайней мере на 5 * лучше, чем другие предложенные запросы:
-- Count
SELECT count(*) FROM (
(SELECT id FROM table1) EXCEPT (SELECT id FROM table2)
) t1_not_in_t2;
-- Get full row
SELECT table1.* FROM (
(SELECT id FROM table1) EXCEPT (SELECT id FROM table2)
) t1_not_in_t2 JOIN table1 ON t1_not_in_t2.id=table1.id;
Имея в виду пункты, сделанные в комментарии @John Woo comment/link выше, я обычно обрабатывал это:
SELECT t1.ID, t1.Name
FROM Table1 t1
WHERE NOT EXISTS (
SELECT TOP 1 NULL
FROM Table2 t2
WHERE t1.ID = t2.ID
)
Существует три основных подхода к этому: not exists
, not in
not exists
и left join/is null
.
SELECT l.*
FROM t_left l
LEFT JOIN
t_right r
ON r.value = l.value
WHERE r.value IS NULL
SELECT l.*
FROM t_left l
WHERE l.value NOT IN
(
SELECT value
FROM t_right r
)
SELECT l.*
FROM t_left l
WHERE NOT EXISTS
(
SELECT NULL
FROM t_right r
WHERE r.value = l.value
)
Какой из них лучше? Ответ на этот вопрос может быть лучше разбить на крупных конкретных поставщиков СУБД. Вообще говоря, следует избегать использования select... where... in (select...)
когда величина количества записей в подзапросе неизвестна. Некоторые поставщики могут ограничивать размер. Oracle, например, имеет ограничение 1000. Лучше всего попробовать все три и показать план выполнения.
В частности, форма PostgreSQL, план выполнения NOT EXISTS
и LEFT JOIN/IS NULL
одинаковы. Лично я предпочитаю вариант NOT EXISTS
потому что он лучше показывает намерение. Ведь семантика в том, что вы хотите найти записи в A, которые не существуют в B.
Старое, но все же золото, специфичное для PostgreSQL: https://explainextended.com/2009/09/16/not-in-vs-not-exists-vs-left-join-is-null-postgresql/
SELECT COUNT(ID) FROM tblA a
WHERE a.ID NOT IN (SELECT b.ID FROM tblB b) --For count
SELECT ID FROM tblA a
WHERE a.ID NOT IN (SELECT b.ID FROM tblB b) --For results