SQL Server – SELECT NOT IN
Estaba hoy haciendo unas consultas de SQL, y me he encontrado con el problemilla que os cuento a continuación.
En concreto,necesitaba un listado de los modelos que no están asociados a ninguna carrocería. Para ello, lo que hago es un SELECT de la tabla de modelos donde la condición del WHERE es que no estén en la tabla de carrocerías (el típico SELECT WHERE NOT IN). Algo parecido a lo siguiente:
SELECT idmodelo FROM modelos WHERE idmodelo NOT IN ( SELECT DISTINCT idmodelo FROM carrocerias )
Mi sorpresa ha sido mayúscula cuando al ejecutar la consulta no salía ningún resultado, ya que sabía a ciencia cierta que había muchos modelos sin ninguna carrocería asociada. He emepzado a darle vueltas, a hacer pruebas varias, y al final he encontrado en un post de Stackoverflow el origen del problema y su solución.
¿Por qué ocurre esto? En la tabla de carrocerías, hay muchas que en su clave de referencia externa a modelo tienen el valor NULL. Al hacer el NOT IN, se intenta comparar el valor del idmodelo con NULL. Si la variable ansi_nulls está activa, la comparación de cualquier valor con NULL da como resultado UNKNOWN. Por eso, al hacer la consulta anterior no salía ningún resultado.
Para evitar esto, en la subconsulta hay que poner en al claúsula WHERE, el “IS NOT NULL”. Al final todo queda así:
SELECT idmodelo FROM modelo WHERE idmodelo NOT IN ( SELECT DISTINCT idmodelo FROM carrocerias WHERE idmodelo IS NOT NULL )
Y ahora sí … el resultado es el esperado
NOTA ADICIONAL: Como bien apunta Ezequiel en el primer comentario (¡muchas gracias!), una manera de hacer esto mismo que pongo en el post con mucho mejor rendimiento es hacer un LEFT JOIN entre las tablas modelos y carrocerías. Quedaría así:
SELECT modelo.idmodelo FROM modelo LEFT JOIN carrocerias ON modelo.idmodelo = carrocerias.idmodelo WHERE carrocerias.idmodelo IS NULL
El LEFT JOIN siempre y cuando se haga sobre campos que tengan algún tipo de índice va a dar un mejor rendimiento normalmente que una subquery. En cualquier caso, ante la duda, siempre debéis mirar el planificador de consultas de SQL.
El hacerlo de la manera que yo ponía es porque para darle claridad al caso la consulta estaba simplificada. En realidad, la subquery hacía unas cuántas cosillas más.
No related posts.
Related posts brought to you by Yet Another Related Posts Plugin.
Si te gustó esta entrada anímate a escribir un comentario o suscribirte al feed y obtener los artículos futuros en tu lector de feeds.
Comentarios
Ruben, creo que otra forma de hacerlo con algo de mejor performace (si no me equivoco) podría ser esta:
SELECT modelo.idmodelo
FROM modelo LEFT JOIN carrocerias ON
modelo.idmodelo = carrocerias.idmodelo
WHERE carrocerias.idmodelo IS NULL
obviamente considerando el hecho que la columna idmodelo en carrocerias es un foreignkey vinculado a modelo.

[...] http://www.analizando.me/sql-server-select-not-in/ November 3, 2010 // MsSQL // No Comments // [...]