Valores NULL en agregaciones, joins y DISTINCT
Descubra cómo se comporta NULL de forma diferente al agrupar, unir y determinar la unicidad
Valores NULL en agregaciones, joins y DISTINCT es una lección gratuita de SQL Interview Prep en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de SQL Interview Prep, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de SQL Interview Prep incluye 4 lecciones en total.
NULL en tres lugares sorprendentes
NULL no se comporta igual en todos los contextos. La lección final abarca los tres contextos cuyo comportamiento sorprende más a los candidatos: funciones de agregación, JOIN y DISTINCT / GROUP BY.
El matiz recurrente es que las funciones de agregación y los filtros tratan NULL como «omítame», mientras que la agrupación y DISTINCT lo tratan como «un valor que es igual a otros NULL». Esa inconsistencia es precisamente lo que exploran los entrevistadores.
Si domina estos casos, habrá cubierto las preguntas más habituales sobre NULL en las entrevistas de SQL.
Las funciones de agregación ignoran NULL
La regla principal es la siguiente: las funciones de agregación omiten los NULL. SUM, AVG, MIN, MAX y COUNT(column) ignoran por completo las entradas NULL en lugar de tratarlas como cero.
Por eso AVG puede devolver un número distinto del esperado. Divide la suma de los valores no NULL entre el número de valores no NULL, no entre el número total de filas.
-- bonus values: 100, 200, NULL
SELECT
SUM(bonus) AS total, -- 300 (NULL ignored)
AVG(bonus) AS average, -- 150 = 300 / 2, not / 3
COUNT(bonus) AS cnt -- 2 (NULL not counted)
FROM employees;COUNT(*) frente a COUNT(column)
Es la pregunta más habitual sobre NULL en las funciones de agregación. COUNT(*) cuenta las filas, incluidas las que contienen NULL. COUNT(column) solo cuenta las filas en las que esa columna es distinta de NULL.
Por tanto, la diferencia entre ambas funciones es exactamente el número de NULL de esa columna. COUNT(DISTINCT column) va un paso más allá: también ignora NULL y elimina los duplicados.
SELECT
COUNT(*) AS rows_total, -- all rows
COUNT(bonus) AS non_null_bonus, -- excludes NULLs
COUNT(DISTINCT bonus) AS distinct_bonus, -- excludes NULLs + dups
COUNT(*) - COUNT(bonus) AS null_bonus
FROM employees;AVG frente a SUM/COUNT(*): una trampa clásica
Los entrevistadores preguntan: «¿AVG(x) es igual que SUM(x) / COUNT(*)?». La respuesta es no cuando hay NULL.
AVG(x) equivale a SUM(x) / COUNT(x), ya que divide entre el número de valores no NULL. Dividir entre COUNT(*) en su lugar trata los NULL como si fueran cero y reduce el promedio.
Si realmente desea contar los NULL como cero, debe indicarlo explícitamente mediante COALESCE.
-- These differ when bonus has NULLs:
SELECT
AVG(bonus) AS avg_ignoring_nulls,
SUM(bonus) * 1.0 / COUNT(*) AS avg_nulls_as_zero,
AVG(COALESCE(bonus, 0)) AS explicit_nulls_as_zero
FROM employees;El caso límite de una agregación con todos los valores NULL
¿Qué devuelve una función de agregación cuando todas las entradas son NULL o no hay filas? Esta es una distinción precisa que les gusta a los entrevistadores:
SUM,AVG,MINyMAXsobre valores todos NULL (o sobre cero filas) devuelven NULL.COUNTsiempre devuelve 0, nunca NULL.
Por tanto, si un informe muestra totales en blanco, una posible causa es un SUM con todos sus valores en NULL. Envuélvalo en COALESCE para mostrar 0.
-- No matching rows or all bonuses NULL:
SELECT SUM(bonus) FROM employees WHERE 1 = 0; -- NULL
SELECT COUNT(bonus) FROM employees WHERE 1 = 0; -- 0
-- Present a clean zero:
SELECT COALESCE(SUM(bonus), 0) FROM employees;NULL en las condiciones de JOIN
En la cláusula ON de un JOIN, NULL = NULL sigue siendo UNKNOWN, por lo que las claves NULL nunca coinciden en un equi-join. Dos filas que tengan NULL como clave de JOIN no se emparejarán.
Esto suele sorprender al hacer JOIN mediante claves foráneas opcionales. Si el comportamiento esperado es hacer coincidir NULL con NULL, necesita un operador seguro frente a NULL (IS NOT DISTINCT FROM o <=>) de la lección anterior.
-- Rows with region IS NULL on both sides do NOT match
SELECT *
FROM a JOIN b ON a.region = b.region;
-- To match NULL-to-NULL (ANSI):
SELECT *
FROM a JOIN b ON a.region IS NOT DISTINCT FROM b.region;NULL generados por JOIN externos
Los JOIN externos generan NULL para las filas sin coincidencia. Después de un LEFT JOIN, todas las columnas del lado derecho son NULL en las filas del lado izquierdo que no encontraron coincidencias.
Esta es la base del patrón de anti-join: utilice WHERE right_table.key IS NULL para encontrar filas sin coincidencia, como clientes sin pedidos.
Pero tenga cuidado: filtrar en WHERE una columna de un JOIN externo puede convertirlo accidentalmente de nuevo en un JOIN interno; este es el tema de la siguiente escena.
-- Find customers who have never ordered (anti-join)
SELECT c.id, c.name
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.id IS NULL;La trampa de NULL al usar WHERE con un JOIN externo
Es un caso engañoso muy habitual. Hace un LEFT JOIN con orders y, después, añade WHERE o.status = 'shipped'. De repente, los clientes sin pedidos desaparecen y el JOIN externo se convierte, en la práctica, en un JOIN interno.
¿Por qué? En las filas sin coincidencia, o.status es NULL, y NULL = 'shipped' es UNKNOWN, por lo que WHERE las descarta. Para conservar las filas sin coincidencia, mueva la condición a la cláusula ON.
-- Accidental inner join: drops customers with no orders
SELECT c.name, o.status
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.status = 'shipped';
-- Correct: keep unmatched customers
SELECT c.name, o.status
FROM customers c
LEFT JOIN orders o
ON o.customer_id = c.id AND o.status = 'shipped';DISTINCT considera todos los NULL iguales
Esta es la incoherencia que sorprende a todo el mundo. Las funciones de agregación omiten NULL, pero DISTINCT conserva exactamente un NULL, considerando todos los NULL como duplicados entre sí.
Por tanto, SELECT DISTINCT bonus aplicado a los valores 100, 100, NULL, NULL devuelve tres filas: 100, NULL y nada más. Los dos NULL se combinan en uno, aunque NULL = NULL sea UNKNOWN en otros contextos.
-- bonus: 100, 100, NULL, NULL, 200
SELECT DISTINCT bonus FROM employees;
-- Returns: 100, 200, NULL (the two NULLs become one row)GROUP BY agrupa los NULL en un solo grupo
GROUP BY sigue la misma regla que DISTINCT: todas las claves NULL se reúnen en un único grupo. Esto es lo contrario de la lógica de comparación, donde los NULL nunca son iguales entre sí.
Por tanto, agrupar por una columna que admite NULL produce una fila que representa todos los registros cuya clave es NULL, que normalmente es lo que se desea para elaborar informes. Mencione este contraste (agrupación frente a comparación) para demostrar un conocimiento profundo.
-- All employees with NULL department form ONE group
SELECT department, COUNT(*) AS headcount
FROM employees
GROUP BY department;
-- A single row where department is NULL totals all of themPuntos clave para la entrevista
El resumen unificador que impresiona a los entrevistadores:
- Las funciones de agregación ignoran NULL; AVG divide entre COUNT(column), no entre COUNT(*).
- COUNT(*) cuenta filas; COUNT(col) y COUNT(DISTINCT col) omiten NULL.
- SUM/AVG/MIN/MAX sobre ninguna fila devuelven NULL; COUNT devuelve 0.
- En los JOIN, las claves NULL nunca coinciden; filtrar en WHERE una columna de un JOIN externo hace que este se convierta silenciosamente en un JOIN interno.
- DISTINCT y GROUP BY consideran todos los NULL iguales, lo contrario de la lógica de comparación.
La frase clave: «NULL se ignora al agregar y comparar, pero se agrupa al eliminar duplicados.»
Comprobación rápida
Ponga a prueba el contraste entre agrupación y agregación.
Repaso
Ha completado el tratamiento de NULL para entrevistas:
- Las funciones de agregación omiten NULL; AVG divide entre la cantidad de valores no NULL, y un SUM con todos sus valores en NULL devuelve NULL, mientras que COUNT devuelve 0.
COUNT(*)incluye las filas con NULL;COUNT(col)no las incluye, y la diferencia equivale a la cantidad de NULL.- Las claves de JOIN que son NULL nunca coinciden; filtrar en WHERE las columnas de un JOIN externo puede hacer que se convierta en un JOIN interno.
- DISTINCT y GROUP BY agrupan todos los NULL en uno solo, lo contrario de la lógica de comparación.
Recuerde esta máxima: NULL se ignora al agregar y comparar, pero se agrupa al eliminar duplicados. Esta única idea responde a la mayoría de las preguntas de entrevista sobre NULL.
Aprende SQL con un tutor de IA — gratis
Escribe y ejecuta código real en tu navegador, obtén ayuda instantánea de un tutor de IA disponible 24/7 y continúa donde lo dejaste en la web o en la aplicación.
- Cursos
- 30
- Lecciones
- 120
Preguntas frecuentes
¿La lección «Valores NULL en agregaciones, joins y DISTINCT» es gratis?
Sí — el texto completo de «Valores NULL en agregaciones, joins y DISTINCT» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de SQL Interview Prep, actualiza a CoddyKit PRO. El curso de SQL Interview Prep incluye 4 lecciones en total.
¿Qué aprenderé en «Valores NULL en agregaciones, joins y DISTINCT»?
Descubra cómo se comporta NULL de forma diferente al agrupar, unir y determinar la unicidad Practicas SQL Interview Prep con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar SQL Interview Prep?
No se requiere experiencia previa. SQL Interview Prep en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.
¿Cuánto tiempo toma la lección «Valores NULL en agregaciones, joins y DISTINCT»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de SQL Interview Prep?
Sí. Cada lección de SQL Interview Prep incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Lógica trivalente y UNKNOWN
- IS NULL, IS NOT NULL e igualdad segura para NULL
- COALESCE, NULLIF e ISNULL
- Valores NULL en agregaciones, joins y DISTINCT