How do I find records that are not joined?

2020-02-20 07:08发布

I have two tables that are joined together.

A has many B

Normally you would do:

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

To get all of the records from a that has a record in b.

How do I get just the records in a that does not have anything in b?

10条回答
一夜七次
2楼-- · 2020-02-20 07:44
SELECT <columnns>
FROM a WHERE id NOT IN (SELECT a_id FROM b)
查看更多
虎瘦雄心在
3楼-- · 2020-02-20 07:51

The first approach is

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

the second approach is

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

The first approach is very expensive. The second approach is better.

With PostgreSql 9.4, I did the "explain query" function and the first query as a cost of cost=0.00..1982043603.32. Instead the join query as a cost of cost=45946.77..45946.78

For example, I search for all products that are not compatible with no vehicles. I've 100k products and more than 1m compatibilities.

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

The join query spent about 5 seconds, instead the subquery version has never ended after 3 minutes.

查看更多
Summer. ? 凉城
4楼-- · 2020-02-20 07:53
select * from a where id not in (select a_id from b)

Or like some other people on this thread says:

select a.* from a
left outer join b on a.id = b.a_id
where b.a_id is null
查看更多
淡お忘
5楼-- · 2020-02-20 07:55
select * from a
left outer join b on a.id = b.a_id
where b.a_id is null
查看更多
再贱就再见
6楼-- · 2020-02-20 07:55

In case of one join it is pretty fast, but when we are removing records from database which has about 50 milions records and 4 and more joins due to foreign keys, it takes a few minutes to do it. Much faster to use WHERE NOT IN condition like this:

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)

I can also recommended this approach for deleting in case we don't have configured cascade delete. This query takes only a few seconds.

查看更多
啃猪蹄的小仙女
7楼-- · 2020-02-20 07:57

Another approach:

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

The "exists" approach is useful if there is some other "where" clause you need to attach to the inner query.

查看更多
登录 后发表回答