h1

[SQL]Select tabla registros no estan en otra tabla

julio 21, 2010

Nunca hay una manera única de hacer las cosas y en el caso de las bases de datos,  lo mejor que podemos hacer es probar y analizar nuestras selects para optimizarlas.

De todas manera vamos con el tema del post:

Seleccionar registros de una tabla que no están en otra tabla:

Supongamos t1 = Tabla Origen, t2 = Tabla donde están los registros que no queremos. Trabajaremos con el campo id pero lo podéis substituir por la clave o claves de vuestras tablas

1) Select * from t1 where not exists (select 1 from t2 where t2.id = t1.id)

Si el campo/s id esta indexado esto va a ser muy rápido y sin problemas. Es posible que inicialmente hayais pensado en un NOT IN al estilo:

2) Select * from t1 where t1.id not in (select t2.id from t2)

Esta segunda opción es altamente ineficiente pues a cada registro se ejecuta la segunda select y la búsqueda en su resultado. Si t2 es grande lo vais a notar mucho.

Podríamos hacer un left join de manera que seleccionamos los que no ha podido hacer el join:

3) Select * from t1 left join t2 on t1.id=t2.id where t2.id is null;

Por algún motivo esta opcion se me antoja fea y prefiero la 1. Aún así puede ser muy ágil, por lo que vale la pena investigar la eficiencia de cada opción y escoger la que más nos complazca.

Hasta pronto!

About these ads

35 comentarios

  1. Gracias,,me sirvio muchisimoo la primera opción,,definitivamente el IN es muy pero muy lento


  2. Muy útil, la primera opción funciona de lujo


  3. Excelente amigo…muy util la informacion


  4. Gracias voy a realizar las pruebas….


  5. Gracias por vuestros comentarios. Hace tiempo que quiero seguir con el blog y esto me anima a hacerlo.


  6. Muchas gracias, me ha ayudado mucho, me quedo con la tercera forma.


  7. O muy buen aporte… en mi caso me sirve mas la opcion 1… Excelente… :-D


  8. no manchen me tarda un chorro cualquiera de las tres y excede el tiempo de ejecución alguna otra??


  9. Maravillosamente , excelso, genial y me quedo sin palabras


  10. ya se pk me tardaba pk no estaban bn indexadas saludos!! excelente tuto


  11. Graciaaaaas =D me has salvado la vida jejejeje bendiciones


  12. Muchas Gracias, muy interessante su aporte.
    Saludos desde Temuco.


  13. Excelente, me sirvio la primera opcion


  14. Muchas gracias. que dios de lo pague.
    Horas sacando una consulta,
    la tercera opción me salvo las ganas de romper mi teclado.


  15. Perfecto. Lo bueno siempre es simple.
    Ya de paso, podrías explicar qué hace el “1″ tras el segundo select?

    Select * from t1 where not exists (select 1 from t2 where t2.id = t1.id)


    • Veràs, en realidad… nada. Es decir, el exists sólo sirve para dar un resultado booleano (cierto/falso) que sera cierto si el resultado de la select devuelve algo, lo que sea (no importa). Por lo tanto podrias poner cualquier cosa, un campo, * o para el caso lo mas simple, un 1.


      • ok! Gracias artista :)


  16. como no tenia indexado los campos a comparar, la 3ra. Opcion me saco del apuro. gracias muchas graciassssss


  17. muy facil de entender…Gracias !


  18. Muy bueno. Gracias


  19. Muchas gracias, me ha sido de gran utilidad.


  20. ami me sirvio mucho el 2 lo uni con mi join y sirvio
    saca todos los ejemplares que no sean prestado

    Select a.CODIGODOC,c.CONSECUTIVO,a.TITULO,a.SUBTITULO,a.IDTEMA,a.ANO from documentos a
    join ejemplares c
    on c.CODIGODOC=a.CODIGODOC
    where a.CODIGODOC not in (select b.CODIGODOC from detprestamo b) order by a.ANO asc


    • El ejemplo 2 es el que no debe utilizarse


  21. Siguiendo el ejemplo 1, si el valor de t1.id en el where fuese con openquery desde sql a oracle, como quedaría?


  22. Excelente , me sirvió mucho el ejemplo 1.


  23. NO sabes la de vueltas que le había dado a esto, me había hecho la picha un lio con el join el exists y el not in… mil gracias!


  24. GRACIAS VIEJO SI QUE ME SIRVIÓ DE MUCHO, ERA JUSTO LO QUE BUSCABA


  25. excelente


  26. Me resulto muy util tuve.. GRacias


  27. me sacaste de un buen apuro, muchas gracias


  28. Siempre habrá alguien que buscará solución a sus problemas y tu debes tener muchas respuestas!
    Por eso te agradezco te pasaste compadre !


  29. Tengo 2 tablas relacionadas con los siguientes atributos

    estado:
    id_es
    mombre_es

    municipio:
    id_mu
    nombre_mu
    id_es

    y quiero hacer una consulta que me diga cuantos municipio tiene cada estado, incluyendo los estados que no posen municipo, osea me arroje algo asi:

    nom_es | Cantidad

    yaracuy 2
    Bolivar 0
    lara 3
    caracas 0

    xfavor alguien que me pueda ayudar


    • Amigo Alejandro,

      A priori parece una consulta muy fácil. No soy partidario de dar soluciones a problemas concretos pues no es la manera de aprender y el objetivo del blog es aprender. Para soluciones directas puedes postear en un stackoverflow, por ejemplo.
      Dicho esto, esta claro que necesitar un agrupador tipo count(*) con un group by y un left join entre las tablas para incluir los que no tienen registros en la tabla hija. Espero que esto te ayude, si quieres preguntar sobre una sql concreta haz un intento y te podremos guiar si hay algun fallo de concepto. Hasta pronto!


  30. PARABÉNS! Era exatamente o que eu estava precisando!
    Quando a quantidade de registros é muito grande a segunda opção demora demais.
    A primeira consulta funcionou muito rápido.
    Obrigado!



Deja un comentario

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

%d personas les gusta esto: