Вопрос

У меня есть две таблицы, которые соединены вместе.

У A есть много B

Обычно вы бы сделали:

select * from a,b where b.a_id = a.id

Чтобы получить все записи из a, у которых есть запись в b.

Как мне получить только записи в a, в которых нет ничего в b?

Это было полезно?

Решение

select * from a where id not in (select a_id from b)

Или, как говорят некоторые другие люди в этой теме:

select a.* from a
left outer join b on a.id = b.a_id
where b.a_id is null

Другие советы

select * from a
left outer join b on a.id = b.a_id
where b.a_id is null

Другой подход:

select * from a where not exists (select * from b where b.a_id = a.id)

Подход "exists" полезен, если есть какое-то другое предложение "where", которое вам нужно присоединить к внутреннему запросу.

SELECT id FROM a
EXCEPT
SELECT a_id FROM b;

выберите * из a, где id отсутствует (выберите a_id из b)

Вероятно, вы получите намного лучшую производительность (чем при использовании 'not in'), если будете использовать внешнее соединение:

select * from a left outer join b on a.id = b.a_id where b.a_id is null;

Это защитит вас от нулей в предложении IN, которые могут вызвать неожиданное поведение.

выберите * из a, где id отсутствует (выберите [a id] из b, где [идентификатор] не равен нулю)

В случае одного объединения это происходит довольно быстро, но когда мы удаляем записи из базы данных, которая содержит около 50 миллионов записей и 4 и более объединений из-за внешних ключей, на это уходит несколько минут.Гораздо быстрее использовать ТАМ, ГДЕ НЕТ такого состояния, как это:

select a.* from a
where a.id NOT IN(SELECT DISTINCT a_id FROM b where a_id IS NOT NULL)
//And for more joins
AND a.id NOT IN(SELECT DISTINCT a_id FROM c where a_id IS NOT NULL)

Я также могу порекомендовать этот подход для удаления в случае, если у нас не настроено каскадное удаление.Этот запрос занимает всего несколько секунд.

Первый подход заключается в следующем

select a.* from a where a.id  not in (select b.ida from b)

второй подход заключается в следующем

select a.*
  from a left outer join b on a.id = b.ida
  where b.ida is null

Первый подход обходится очень дорого.Второй подход лучше.

В PostgreSQL 9.4 я выполнил функцию "объяснить запрос" и первый запрос в качестве стоимости стоимость=0,00..1982043603,32.Вместо этого запрос join в качестве стоимости стоимость=45946,77..45946,78

Например, я ищу все продукты, которые несовместимы ни с какими транспортными средствами.У меня есть 100 тысяч продуктов и более 1 миллиона совместимых.

select count(*) from product a left outer join compatible c on a.id=c.idprod where c.idprod is null

Запрос объединения затратил около 5 секунд, вместо этого версия подзапроса так и не завершилась через 3 минуты.

Другой способ написать это

select a.*
from a 
left outer join b
on a.id = b.id
where b.id is null

Ой, Натан побит :)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top