COALESCE
La función COALESCE recorre una lista de expresiones de izquierda a derecha y devuelve la primera que no sea NULL. Si todas son NULL, devuelve NULL. Es la versión generalizada de IFNULL: mientras que IFNULL acepta exactamente dos argumentos, COALESCE acepta cualquier número, lo que la convierte en la herramienta ideal para establecer cadenas de valores de respaldo.
Además, COALESCE forma parte del estándar ANSI SQL, por lo que funciona de la misma manera en MySQL, PostgreSQL, SQL Server y Oracle. Si escribes consultas que pueden ejecutarse en diferentes motores de base de datos, COALESCE es la opción más portable. A diferencia de funciones como IFNULL o NVL, que son específicas de cada motor, COALESCE te garantiza compatibilidad sin modificar ni una sola línea de tu consulta al migrar entre sistemas.
En la práctica diaria, COALESCE aparece en casi cualquier proyecto que interactúe con bases de datos reales, porque los valores NULL son inevitables: campos opcionales que el usuario no rellenó, columnas que aún no tienen datos, resultados de LEFT JOIN que no encontraron coincidencia o funciones de agregación que devuelven NULL cuando no hay filas. Sin una herramienta para manejar estos casos, tus reportes y pantallas mostrarían celdas vacías o errores inesperados. COALESCE convierte esos huecos en valores legibles y consistentes.
Sintaxis
La sintaxis de COALESCE es directa: recibe una lista de expresiones separadas por comas y devuelve la primera que no sea NULL.
COALESCE(expresion1, expresion2, ..., expresionN)MySQL evalúa las expresiones en orden, de izquierda a derecha. En cuanto encuentra una que no es NULL, la devuelve y deja de evaluar las restantes. Esto significa que las expresiones más probables de tener valor deberían ir primero por eficiencia, aunque en la práctica la diferencia de rendimiento es insignificante. La función requiere al menos una expresión, pero no tiene un limite superior definido en la documentacion oficial. En escenarios reales, rara vez se usan mas de cuatro o cinco argumentos, ya que una cadena de respaldo demasiado larga dificulta la lectura.
Comportamiento basico
Para entender cómo funciona la evaluación en cascada, observa cómo MySQL procesa distintas combinaciones de valores NULL y no NULL en una misma consulta.
SELECT
COALESCE(NULL, NULL, 'tercero') AS ejemplo1,
COALESCE(NULL, 'segundo', 'tercero') AS ejemplo2,
COALESCE('primero', 'segundo') AS ejemplo3,
COALESCE(NULL, NULL, NULL) AS ejemplo4;| ejemplo1 | ejemplo2 | ejemplo3 | ejemplo4 |
|---|---|---|---|
| tercero | segundo | primero | NULL |
En el primer caso, las dos primeras expresiones son NULL, así que devuelve la tercera. En el segundo, la primera es NULL pero la segunda tiene valor, y se devuelve directamente sin evaluar la tercera. En el tercero, la primera expresión ya tiene valor, así que ni siquiera se evalúa la segunda. En el cuarto, todas son NULL, y el resultado es NULL. Este ultimo caso es importante tenerlo presente: si existe la posibilidad de que todos los argumentos sean nulos, deberías incluir un literal al final de la cadena como valor de ultimo recurso.
Un uso inmediato es proporcionar valores por defecto al mostrar datos de una tabla. Imagina una tabla de clientes donde algunos tienen teléfono secundario y otros no. En lugar de mostrar celdas vacías en un informe, puedes construir una columna que siempre tenga un valor significativo.
SELECT
nombre,
COALESCE(telefono_secundario, telefono, 'Sin contacto') AS mejor_telefono
FROM clientes
LIMIT 6;| nombre | mejor_telefono |
|---|---|
| María | 611223344 |
| Carlos | 612345678 |
| Ana | 633445566 |
| Pedro | 698765432 |
| Lucía | 655667788 |
| Javier | 678901234 |
Para cada cliente, MySQL intenta primero el teléfono secundario. Si es NULL, usa el teléfono principal. Si ambos fueran NULL (algo improbable pero posible), mostraría el texto 'Sin contacto'. Con IFNULL necesitarías anidar dos llamadas para lograr lo mismo: IFNULL(telefono_secundario, IFNULL(telefono, 'Sin contacto')). La ventaja de COALESCE queda clara cuando la cadena tiene tres, cuatro o más niveles de respaldo, porque evita la anidación que dificulta la lectura.
Caso práctico: cadena de contacto de respaldo
En sistemas de atención al cliente es habitual tener múltiples canales de contacto, pero no todos los clientes proporcionan todos. Un formulario de registro podría pedir el email de trabajo, el personal y uno alternativo, pero la mayoría de personas solo completan uno o dos de esos campos. COALESCE permite seleccionar el mejor canal disponible sin necesidad de escribir bloques condicionales IF o expresiones CASE.
SELECT
nombre,
apellidos,
COALESCE(email_trabajo, email_personal, email_alternativo) AS email_contacto,
COALESCE(telefono_movil, telefono_fijo, telefono_empresa) AS telefono_contacto
FROM clientes
LIMIT 6;| nombre | apellidos | email_contacto | telefono_contacto |
|---|---|---|---|
| María | García López | maria.garcia@empresa.com | 611223344 |
| Carlos | Rodríguez Martín | carlos.rodriguez@email.com | 622334455 |
| Ana | Martínez Ruiz | ana.martinez@trabajo.com | 633445566 |
| Pedro | Fernández Castro | pedro.fernandez@email.com | 698765432 |
| Lucía | Sánchez Moreno | lucia.sanchez@email.com | 655667788 |
| Javier | López García | javier@empresa.com | 678901234 |
La prioridad de contacto queda definida por el orden de los argumentos: primero el email de trabajo, luego el personal, y finalmente el alternativo. Si reorganizas los argumentos, cambias la prioridad. Esta es una forma declarativa y fácil de mantener para definir reglas de negocio de contacto. Cualquier desarrollador que lea la consulta entiende al instante cuál es la jerarquía de preferencia sin necesidad de documentación adicional.
Caso práctico: fusionar columnas de un JOIN
Cuando unes varias tablas que tienen columnas equivalentes, COALESCE permite fusionarlas en una sola columna coherente. Este patrón es especialmente común con múltiples LEFT JOIN, donde las filas sin correspondencia producen valores NULL en todas las columnas de la tabla derecha.
Consideremos un escenario habitual en comercio electrónico: un producto fue eliminado del catálogo, pero sus líneas de pedido históricas siguen existiendo. Si haces un LEFT JOIN contra la tabla de productos, las columnas del producto serán NULL para esos registros eliminados. Sin embargo, la tabla de detalle del pedido suele guardar una copia del nombre y el precio en el momento de la compra, precisamente para este tipo de situaciones.
SELECT
COALESCE(p.nombre, d.nombre_pedido) AS producto,
COALESCE(p.precio, d.precio_unitario) AS precio,
d.cantidad,
COALESCE(p.precio, d.precio_unitario) * d.cantidad AS subtotal
FROM detalle_pedidos d
LEFT JOIN productos p ON d.producto_id = p.id
WHERE d.pedido_id = 5
ORDER BY subtotal DESC;| producto | precio | cantidad | subtotal |
|---|---|---|---|
| ASUS ROG Zephyrus | 1899.99 | 1 | 1899.99 |
Si un producto fue eliminado del catálogo pero su registro sigue en el detalle del pedido, p.nombre sería NULL porque el LEFT JOIN no encontraría coincidencia. COALESCE recurre entonces a d.nombre_pedido, un campo que almacena una copia del nombre en el momento de la compra. Este patrón garantiza que los reportes históricos nunca muestren datos vacíos, independientemente de los cambios en el catálogo. Es una práctica tan extendida que muchos ORMs y frameworks de reporting la aplican automáticamente cuando detectan joins externos.
Caso práctico: valores calculados con respaldo
COALESCE también funciona con expresiones calculadas, no solo con columnas directas. Esto es útil para construir métricas con niveles de precisión decrecientes, donde cada nivel de respaldo ofrece una estimación menos exacta pero garantiza que siempre exista un valor disponible para el análisis.
Imaginemos una tabla de productos donde algunos tienen un margen de beneficio registrado manualmente por el equipo de finanzas, otros tienen el precio y el coste (a partir de los cuales se puede calcular el margen), y unos pocos solo tienen el precio de venta. Queremos obtener siempre un margen estimado, usando la mejor fuente disponible.
SELECT
nombre,
precio,
coste,
margen_manual,
COALESCE(
margen_manual,
precio - coste,
precio * 0.30
) AS margen_estimado
FROM productos
WHERE categoria_id = 6;| nombre | precio | coste | margen_manual | margen_estimado |
|---|---|---|---|---|
| iPhone 15 Pro | 1299.99 | 850.00 | 450.00 | 450.00 |
| Samsung Galaxy S24 | 899.99 | 580.00 | NULL | 319.99 |
| Google Pixel 8 | 699.00 | NULL | NULL | 209.70 |
| Xiaomi 14 | 599.99 | 390.00 | NULL | 209.99 |
La cadena de respaldo funciona así: primero se usa el margen registrado manualmente (si existe), luego se calcula a partir del precio y el coste (si ambos tienen valor), y finalmente se estima como el 30% del precio (si todo lo anterior es NULL). Observa un detalle importante: cuando coste es NULL, la expresión precio - coste también devuelve NULL (porque cualquier operación aritmética con NULL produce NULL), y entonces COALESCE pasa automáticamente al tercer argumento. Esto es una ventaja, no un problema, porque el comportamiento de propagación de NULL en aritmética trabaja a nuestro favor.
Uso en cláusulas WHERE y ORDER BY
Aunque el uso más frecuente de COALESCE es en la lista del SELECT, también resulta muy útil en las cláusulas WHERE y ORDER BY. En la cláusula WHERE, puedes usar COALESCE para comparar contra un valor por defecto cuando la columna podría ser NULL.
SELECT nombre, precio, fecha_descuento
FROM productos
WHERE COALESCE(fecha_descuento, '9999-12-31') > CURDATE()
ORDER BY COALESCE(fecha_descuento, '9999-12-31') ASC;En esta consulta, los productos sin fecha de descuento (es decir, con fecha_descuento igual a NULL) se tratan como si la fecha fuera en un futuro lejano, lo que los coloca al final del resultado ordenado. Sin COALESCE, tendrías que manejar los NULL por separado con una condición adicional, ya que las comparaciones directas con NULL siempre devuelven NULL (ni verdadero ni falso).
Otro patrón frecuente en ORDER BY es asignar un valor de ordenación por defecto para que los registros sin datos no queden dispersos de forma impredecible.
SELECT nombre, COALESCE(prioridad, 999) AS prioridad_efectiva
FROM tareas
ORDER BY COALESCE(prioridad, 999) ASC, fecha_creacion DESC;Las tareas sin prioridad asignada reciben el valor 999, lo que las envía al final del listado. Este enfoque es mucho más limpio que usar CASE WHEN prioridad IS NULL THEN 999 ELSE prioridad END.
Manejo de NULL y tipos de datos
COALESCE trata los valores NULL de forma transparente, pero hay un detalle sobre los tipos de datos que conviene conocer. Cuando mezclas tipos diferentes en los argumentos, MySQL determina el tipo del resultado basándose en todos los argumentos, no solo en el que devuelve.
SELECT
COALESCE(NULL, NULL, 42) AS numero,
COALESCE(NULL, 'texto', 42) AS mixto,
COALESCE(NULL, NULL, NOW()) AS fecha;| numero | mixto | fecha |
|---|---|---|
| 42 | texto | 2026-02-14 15:30:00 |
En el caso de mixto, aunque devuelve 'texto', MySQL considera que la columna podría contener también un número (42), así que ajusta el tipo internamente. En la práctica esto rara vez causa problemas, pero si necesitas un tipo específico en el resultado, puedes usar CAST para forzarlo.
SELECT COALESCE(CAST(campo_numerico AS CHAR), campo_texto, 'N/A') AS resultado;Otro aspecto a tener en cuenta es que COALESCE con un solo argumento simplemente devuelve ese argumento (o NULL si es NULL). Aunque no tiene sentido práctico, es un comportamiento válido y no produce errores. En entornos donde las consultas se generan dinámicamente (por ejemplo, desde un ORM o un constructor de queries), es útil saber que COALESCE no fallará si recibe un solo argumento.
Combinación con otras funciones
COALESCE se combina frecuentemente con CONCAT para construir cadenas que incluyen datos opcionales. Esta combinación aprovecha un comportamiento particular de CONCAT en MySQL: si cualquiera de sus argumentos es NULL, todo el resultado es NULL. Esto permite crear patrones elegantes donde COALESCE actúa como interruptor.
SELECT
CONCAT(
nombre,
' ',
apellidos,
COALESCE(CONCAT(' (', apodo, ')'), '')
) AS nombre_display
FROM clientes
LIMIT 5;| nombre_display |
|---|
| María García López |
| Carlos Rodríguez Martín (Charlie) |
| Ana Martínez Ruiz |
| Pedro Fernández Castro (Pete) |
| Lucía Sánchez Moreno |
Si el cliente tiene apodo, se muestra entre paréntesis. Si no, COALESCE devuelve una cadena vacía que no afecta al resultado. El truco está en que CONCAT(' (', NULL, ')') devuelve NULL (porque cualquier CONCAT con NULL produce NULL), y entonces COALESCE selecciona la cadena vacía alternativa.
También se usa con funciones de agregación en subconsultas para proporcionar valores por defecto. Las funciones como SUM, AVG o MAX devuelven NULL cuando no hay filas que cumplan la condición, lo cual es un problema frecuente al generar informes de clientes que aún no han realizado compras.
SELECT
c.nombre,
c.apellidos,
COALESCE(
(SELECT SUM(p.total) FROM pedidos p WHERE p.cliente_id = c.id AND p.estado = 'entregado'),
0
) AS total_comprado,
COALESCE(
(SELECT MAX(p.fecha_pedido) FROM pedidos p WHERE p.cliente_id = c.id),
'Nunca'
) AS ultima_actividad
FROM clientes c
ORDER BY total_comprado DESC
LIMIT 6;| nombre | apellidos | total_comprado | ultima_actividad |
|---|---|---|---|
| María | García López | 1349.98 | 2025-10-15 09:30:00 |
| Carlos | Rodríguez Martín | 1949.98 | 2025-10-22 18:10:00 |
| Ana | Martínez Ruiz | 1899.99 | 2025-10-25 16:45:00 |
| Pedro | Fernández Castro | 79.98 | 2025-12-05 11:15:00 |
| Sandra | Blanco Calvo | 0 | Nunca |
| Fernando | Díaz Navarro | 0 | Nunca |
Las subconsultas devuelven NULL cuando no hay filas que cumplan la condición (por ejemplo, clientes sin pedidos entregados). COALESCE convierte esos NULL en valores legibles: 0 para los importes y 'Nunca' para las fechas. Sin esta conversión, el frontend tendría que manejar NULL por separado, duplicando la lógica de presentación.
COALESCE frente a IFNULL y NULLIF
Es habitual confundir estas tres funciones porque las tres trabajan con valores NULL, pero cada una tiene un propósito distinto. IFNULL acepta exactamente dos argumentos y devuelve el segundo si el primero es NULL. Es funcionalmente equivalente a COALESCE con dos argumentos, pero no es estándar SQL. NULLIF hace lo opuesto: recibe dos argumentos y devuelve NULL si ambos son iguales. Es útil para evitar divisiones por cero o para convertir valores centinela en NULL.
La combinación de NULLIF y COALESCE es un patrón avanzado que permite reemplazar valores centinela (como cadenas vacías o ceros) por textos descriptivos.
SELECT
nombre,
COALESCE(NULLIF(telefono, ''), 'No proporcionado') AS telefono_limpio
FROM clientes
LIMIT 4;En este ejemplo, NULLIF(telefono, '') convierte las cadenas vacías en NULL, y luego COALESCE reemplaza ese NULL por el texto 'No proporcionado'. Sin esta combinación, los campos vacíos (que técnicamente no son NULL) pasarían desapercibidos y aparecerían como celdas en blanco en los reportes.
Errores comunes
El error más frecuente con COALESCE es olvidar que las operaciones aritméticas con NULL propagan el nulo. Si escribes COALESCE(precio * descuento, precio) y descuento es NULL, la expresión precio * descuento ya es NULL aunque precio tenga valor, así que COALESCE saltará al segundo argumento. Esto suele ser el comportamiento deseado, pero si no lo esperas puede causar confusión al depurar.
Otro error habitual es asumir que COALESCE ignora cadenas vacías. Una cadena vacía '' no es NULL en MySQL; es un valor perfectamente válido. Si necesitas tratar cadenas vacías como si fueran nulas, combina COALESCE con NULLIF como se mostró en la sección anterior.
Finalmente, ten cuidado al usar COALESCE en la cláusula WHERE sobre columnas indexadas. Envolver una columna en una función impide que MySQL utilice el índice de esa columna, lo que puede degradar el rendimiento en tablas grandes. Si el rendimiento es crítico, considera reestructurar la condición para evitar la función sobre la columna indexada, o utiliza un índice funcional si tu versión de MySQL lo soporta.
Cuándo usar COALESCE
En términos de portabilidad, COALESCE es siempre la opción recomendada sobre IFNULL cuando escribes SQL que podría ejecutarse en diferentes motores de base de datos. IFNULL es específica de MySQL, mientras que COALESCE es parte del estándar SQL y funciona en todos los sistemas relacionales principales. Si solo necesitas detectar si un valor es nulo sin sustituirlo, utiliza ISNULL.
Usa COALESCE siempre que necesites garantizar que una expresión nunca devuelva NULL: en columnas de reportes que se exportan a Excel o PDF, en cálculos donde un NULL propagaría nulos en cadena, en la construcción de cadenas con CONCAT, en la asignación de valores por defecto para parámetros opcionales de procedimientos almacenados, o en la fusión de columnas procedentes de joins externos. Es una de las funciones más versátiles de SQL y una de las primeras que cualquier desarrollador debería dominar.
Practica con COALESCE
Usa el editor para seleccionar el primer valor no nulo con COALESCE:
En el siguiente artículo veremos ISNULL para verificar si un valor es NULL.
Escrito por Eduardo Lázaro
