Coding Interview Prep · Lección

Valores NULL en agregaciones, joins y DISTINCT

Descubra cómo se comporta NULL de forma diferente al agrupar, unir y determinar la unicidad

Lección 4 de 413 pasos

Valores NULL en agregaciones, joins y DISTINCT es una lección gratuita de Coding 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 Coding Interview Prep, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Coding 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, MIN y MAX sobre valores todos NULL (o sobre cero filas) devuelven NULL.
  • COUNT siempre 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 them

Puntos 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.

Gratis para empezar

Aprende Coding Interview Prep 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
90
Lecciones
360

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 Coding Interview Prep, actualiza a CoddyKit PRO. El curso de Coding 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 Coding 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 Coding Interview Prep?

No se requiere experiencia previa. Coding 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 Coding Interview Prep?

Sí. Cada lección de Coding 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

  1. Lógica trivalente y UNKNOWN
  2. IS NULL, IS NOT NULL e igualdad segura para NULL
  3. COALESCE, NULLIF e ISNULL
  4. Valores NULL en agregaciones, joins y DISTINCT
← Volver a Coding Interview Prep