1. Faro

Nivel 5 · La trampa de comparar con NULL

La solicitud

De Lauren Hayes, Gerente de Email Marketing

“Una comprobación rápida antes de enviar una encuesta: quiero a todos los clientes cuya fuente de referencia no sea 'google_ads', incluidos aquellos de los que nunca registramos una fuente. ¿Qué filtro me da eso?”

Tu objetivo

Elige la cláusula WHERE que devuelve a todos los clientes cuyo referral_source no es 'google_ads', incluidos los clientes cuyo referral_source es NULL.

¿Qué cláusula WHERE devuelve a todos los clientes cuyo referral_source no es 'google_ads', incluidos los clientes sin referral_source registrado?

Elige una respuesta y luego compruébala.

La lección

NULL significa “desconocido” o “no registrado”. No es cero, no es una cadena vacía y no es igual a nada, ni siquiera a otro NULL. Ese solo hecho causa más números equivocados que cualquier otra parte de SQL.

Lógica de tres valores

Las condiciones de SQL pueden ser verdaderas, falsas o desconocidas. Cualquier comparación que involucre NULL es desconocida:

expresión resultado
NULL = 'google_ads' desconocido
NULL <> 'google_ads' desconocido
NULL = NULL desconocido
NULL IS NULL verdadero

WHERE conserva una fila solo cuando su condición es verdadera. Las filas desconocidas se descartan, en silencio, igual que las falsas.

IS NULL e IS NOT NULL

Para comprobar un valor que falta, usa los operadores específicos:

SELECT customer_id, email
FROM customers
WHERE referral_source IS NULL;

WHERE referral_source = NULL es sintaxis válida, se ejecuta sin error y devuelve cero filas siempre. Algunas herramientas te avisan; la mayoría no.

La trampa del distinto

Esta es la versión que muerde a los analistas en informes reales. Supón que algunos clientes no tienen fuente de referencia registrada y quieres “todos menos google_ads”:

-- drops every NULL row
WHERE referral_source <> 'google_ads'

Para una fila NULL, NULL <> 'google_ads' es desconocido, así que la fila desaparece. Tu audiencia “que no viene de Google Ads” es más pequeña de lo que debería, y las filas que perdiste son justo de las que menos sabes. La solución es decir lo que quieres sobre los NULL:

WHERE referral_source <> 'google_ads' OR referral_source IS NULL

Postgres, DuckDB y BigQuery también admiten la comparación segura con nulos referral_source IS DISTINCT FROM 'google_ads', que trata NULL como un valor ordinario. La versión de MySQL es el operador <=>: NOT (referral_source <=> 'google_ads').

NULL con AND y OR

  • true AND unknown es desconocido; false AND unknown es falso.
  • true OR unknown es verdadero; false OR unknown es desconocido.
  • NOT unknown sigue siendo desconocido, por eso NOT referral_source = 'google_ads' también descarta los NULL.

Nota de entrevista

“¿Qué se pierde SELECT COUNT(*) FROM customers WHERE referral_source <> 'google_ads'?” es una pregunta clásica de filtro. La respuesta que quieren los entrevistadores: las filas donde referral_source es NULL, porque la comparación es desconocida y WHERE conserva solo las filas verdaderas. Menciona IS NULL o IS DISTINCT FROM como la solución y sonarás como alguien a quien ya le ha pasado.

Errores comunes

  • Escribir WHERE referral_source = NULL. Se ejecuta sin error y siempre devuelve cero filas. Usa WHERE referral_source IS NULL.
  • Confiar en que <> conserve las filas NULL. WHERE referral_source <> 'google_ads' descarta a todos los clientes sin fuente. Escribe WHERE referral_source <> 'google_ads' OR referral_source IS NULL.
  • Esperar que NOT IN o NOT ayuden. referral_source NOT IN ('google_ads', 'email') y NOT referral_source = 'google_ads' descartan las filas NULL de la misma forma.
  • Tratar una cadena vacía como valor que falta. WHERE referral_source = '' encuentra texto en blanco, no NULL. Si una columna puede contener ambos, comprueba los dos.

En SQL Server

La lógica de tres valores es idéntica: = NULL y <> 'google_ads' descartan las filas NULL allí también, y la respuesta es la misma versión con IS NULL. SQL Server añade ISNULL(a, b), un COALESCE de dos argumentos: WHERE ISNULL(referral_source, '') <> 'google_ads' también funciona, pero el OR ... IS NULL explícito se lee mejor.

Elige qué puede ejecutarse en este sitio. Puedes cambiarlo cuando quieras desde "Configurar cookies", al pie de cada página.