2011-12-11 24 views
55

estoy tratando de ejecutar esta consulta:PostgreSQL 'NO EN' y subconsulta

SELECT mac, creation_date 
FROM logs 
WHERE logs_type_id=11 
AND mac NOT IN (select consols.mac from consols) 

Pero no da resultados positivos. Lo probé, y sé que hay algo mal con la sintaxis. En MySQL, tal consulta funciona perfectamente. He agregado una fila para asegurarme de que hay una mac que no existe en la tabla consols, pero aún así no está dando ningún resultado.

+4

¿La columna 'consols.mac'' NULL' o 'NOT NULL'? –

Respuesta

96

Cuando se utiliza NO EN debe asegurarse de que ninguno de los valores son nulos:

SELECT mac, creation_date 
FROM logs 
WHERE logs_type_id=11 
AND mac NOT IN (
    SELECT mac 
    FROM consols 
    WHERE mac IS NOT NULL -- add this 
) 
+2

Nota: la cláusula 'WHERE mac IS NOT NULL' en la subconsulta no es necesaria, ya que' In (...) 'siempre elimina NULLs (y duplicados). Debido a que un conjunto no puede contener NULL – wildplasser

+3

@wildplasser, no sé por qué. No funcionó para mí, hasta que agregué el 'IS NOT NULL'. El 'SELECT' anidado estaba retornando unos' NULLS', y eso estaba tropezando con 'IN (SELECT ...)'. – robins35

+1

Agradecería mucho una explicación de por qué el 'IS NOT NULL' hace que esto funcione. – mbarkhau

25

Cuando se utiliza NO EN, también se debe tener en cuenta no existe, que se ocupa de los casos nulos en silencio.

SELECT mac, creation_date 
FROM logs lo 
WHERE logs_type_id=11 
AND NOT EXISTS (
    SELECT * 
    FROM consols nx 
    WHERE nx.mac = lo.mac 
); 
+1

También tenga en cuenta una gran pérdida de rendimiento al utilizar 'NOT EXISTS' vs' ... NOT IN' – IcanDivideBy0

+1

@ IcanDivideBy0 En la mayoría casos que generan el mismo plan de consulta. ¿Lo has probado? – wildplasser

6

También es posible usar una combinación izquierda y la condición IS NULL:

SELECT 
    mac, 
    creation_date 
FROM 
    logs 
    LEFT JOIN consols ON logs.mac = consols.mac 
WHERE 
    logs_type_id=11 
AND 
    consols.mac IS NULL; 

un índice en las columnas "Mac" podría mejorar el rendimiento.