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