Как мне найти записи, которые не объединены? - PullRequest
43 голосов
/ 30 сентября 2008

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

А имеет много B

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

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

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

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

Ответы [ 10 ]

70 голосов
/ 30 сентября 2008
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
16 голосов
/ 30 сентября 2008
select * from a
left outer join b on a.id = b.a_id
where b.a_id is null
5 голосов
/ 30 сентября 2008

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

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

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

4 голосов
/ 13 марта 2012
SELECT id FROM a
EXCEPT
SELECT a_id FROM b;
2 голосов
/ 30 сентября 2008

выберите * из идентификатора, где нет (выберите a_id из b)

1 голос
/ 30 сентября 2008

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

select * from a left outer join b on a.id = b.a_id where b.a_id is null;
0 голосов
/ 16 января 2018

Первый подход

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 я выполнил функцию «объяснить запрос» и первый запрос в виде стоимости cost = 0.00..1982043603.32 . Вместо этого запрос соединения как стоимость стоимость = 45946.77..45946.78

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

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

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

0 голосов
/ 05 января 2018

В случае одного соединения это происходит довольно быстро, но когда мы удаляем записи из базы данных, которая содержит около 50 миллионов записей и 4 и более соединений из-за внешних ключей, это занимает несколько минут. Намного быстрее использовать WHERE NOT IN условие как это:

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)

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

0 голосов
/ 30 сентября 2008

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

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

0 голосов
/ 30 сентября 2008

Другой способ написания

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

Ой, побитый Натаном :) 1004 *

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...