Pregunta

Tengo dos tablas que están unidas.

A tiene muchos B

Normalmente harías:

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

Para obtener todos los registros de a que tiene un registro en b.

¿Cómo obtengo solo los registros en a que no tienen nada en b?

¿Fue útil?

Solución

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

O como dicen otras personas en este hilo:

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

Otros consejos

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

Otro enfoque:

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

El " existe " enfoque es útil si hay algún otro " donde " cláusula que necesita adjuntar a la consulta interna.

SELECT id FROM a
EXCEPT
SELECT a_id FROM b;

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

Probablemente obtendrá un rendimiento mucho mejor (que usar 'no en') si usa una combinación externa:

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

Esto lo protegerá de los nulos en la cláusula IN, lo que puede causar un comportamiento inesperado.

seleccione * de una identificación donde no está (seleccione [una identificación] de b donde [una identificación] no es nula )

En caso de una unión, es bastante rápido, pero cuando estamos eliminando registros de la base de datos que tiene alrededor de 50 millones de registros y 4 y más uniones debido a claves foráneas, lleva unos minutos hacerlo. Mucho más rápido de usar WHERE NOT IN condición como esta:

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)

También puedo recomendar este enfoque para eliminar en caso de que no hayamos configurado la eliminación en cascada. Esta consulta solo lleva unos segundos.

El primer enfoque es

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

el segundo enfoque es

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

El primer enfoque es muy costoso. El segundo enfoque es mejor.

Con PostgreSql 9.4, hice la " explicación de consulta " función y la primera consulta como un costo de costo = 0.00..1982043603.32 . En cambio, la consulta de unión como un costo de cost=45946.77..45946.78

Por ejemplo, busco todos los productos que no son compatibles con ningún vehículo. Tengo 100k productos y más de 1m de compatibilidades.

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

La consulta de unión pasó aproximadamente 5 segundos, en cambio la versión de subconsulta nunca terminó después de 3 minutos.

Otra forma de escribirlo

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

Ay, golpeado por Nathan :)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top