una tablas tabla seleccionar registros que otra existan estan datos consultar comparar coincidentes buscar sql select join anti-join

sql - tablas - ¿Cómo encuentro registros que no están unidos?



consultar dos tablas sql (10)

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 caro. El segundo enfoque es mejor.

Con PostgreSql 9.4, hice la función "explicar consulta" y la primera consulta como un costo de costo = 0.00..1982043603.32 . En cambio, la consulta de combinación como un costo de costo = 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 gastó aproximadamente 5 segundos, en cambio, la versión de la subconsulta nunca finalizó después de 3 minutos.

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 tenga un registro en b.

¿Cómo obtengo solo los registros en un archivo que no tiene nada en b?


En el caso de una unión, es bastante rápido, pero cuando eliminamos registros de la base de datos que tiene aproximadamente 50 millones de registros y 4 y más uniones debido a claves externas, lleva unos minutos hacerlo. Mucho más rápido de usar DONDE NO EN CONDICIONES 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 tengamos configurado la eliminación en cascada. Esta consulta solo lleva unos segundos.


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

select * from a where id not in (seleccione [a id] de b donde [a id] no es nulo )


Otra forma de escribirlo

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

Ouch, golpeado por Nathan :)


Otro enfoque:

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

El enfoque "existe" es útil si hay alguna otra cláusula "donde" que deba adjuntar a la consulta interna.


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;


selecciona * de a donde no está el ID (selecciona un_id de b)


SELECT id FROM a EXCEPT SELECT a_id FROM b;


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


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

O como algunas otras personas en este hilo dice:

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