MAX

La función MAX devuelve el valor más grande de un conjunto de valores. Es la contraparte de MIN y comparte muchas de sus características: funciona con números, fechas, cadenas de texto e ignora los valores NULL. La usarás cuando necesites encontrar el precio más alto, la fecha más reciente, el pedido más grande o el último registro cronológicamente.

Sintaxis

MAX(expresion)

MAX acepta una columna o cualquier expresión que devuelva un valor comparable. Al igual que MIN, funciona con cualquier tipo de dato que MySQL pueda ordenar. Sin GROUP BY, devuelve el máximo de toda la tabla. Con GROUP BY, devuelve el máximo de cada grupo.

Comportamiento básico

Para encontrar el producto más caro del catálogo:

SELECT
    MAX(precio) AS precio_maximo,
    MIN(precio) AS precio_minimo,
    ROUND(AVG(precio), 2) AS precio_medio
FROM productos;
precio_maximoprecio_minimoprecio_medio
1899.999.99384.52

El producto más caro cuesta 1899.99 euros. Mostrar el mínimo y la media junto al máximo da contexto: el máximo está muy por encima de la media, lo que indica que hay unos pocos productos de gama muy alta.

MAX con fechas devuelve la fecha más reciente:

SELECT
    MAX(fecha_pedido) AS ultimo_pedido,
    MAX(fecha_registro) AS ultimo_cliente_registrado
FROM pedidos p
JOIN clientes cl ON p.cliente_id = cl.id;
ultimo_pedidoultimo_cliente_registrado
2026-02-102026-01-28

Este patrón es muy útil para saber cuándo ocurrió la última actividad en el sistema.

Caso práctico: precio máximo por categoría

Con GROUP BY puedes encontrar el producto más caro de cada categoría:

SELECT
    c.nombre AS categoria,
    MAX(p.precio) AS precio_maximo,
    ROUND(AVG(p.precio), 2) AS precio_medio,
    ROUND((MAX(p.precio) - AVG(p.precio)) / AVG(p.precio) * 100, 1) AS pct_sobre_media
FROM productos p
JOIN categorias c ON p.categoria_id = c.id
GROUP BY c.nombre
ORDER BY precio_maximo DESC;
categoriaprecio_maximoprecio_mediopct_sobre_media
Portátiles1899.991245.5052.5
Smartphones1299.99785.4265.5
Deportes449.99189.99136.8
Hogar299.99124.80140.4
Ropa mujer149.9964.99130.8
Ropa hombre129.9959.99116.7
Accesorios electrónicos89.9942.85110.0
Libros29.9922.5033.3

La columna pct_sobre_media muestra cuánto supera el producto más caro a la media de su categoría. Hogar y Deportes tienen los porcentajes más altos, lo que indica que su producto estrella está muy por encima del resto.

Caso práctico: encontrar la fila con el valor máximo

Al igual que con MIN, un problema frecuente es obtener la fila completa que contiene el valor máximo. Por ejemplo, encontrar el pedido más reciente de cada cliente:

SELECT
    cl.nombre,
    cl.apellidos,
    p.id AS pedido_id,
    p.fecha_pedido,
    p.total
FROM pedidos p
JOIN clientes cl ON p.cliente_id = cl.id
WHERE p.fecha_pedido = (
    SELECT MAX(p2.fecha_pedido)
    FROM pedidos p2
    WHERE p2.cliente_id = p.cliente_id
)
ORDER BY p.fecha_pedido DESC
LIMIT 5;
nombreapellidospedido_idfecha_pedidototal
MaríaGarcía López3482026-02-10856.99
CarlosRodríguez Martín3452026-02-081245.00
LauraFernández Díaz3422026-02-05432.50
AnaMartínez Ruiz3402026-02-03678.90
PedroSánchez Gómez3372026-01-301589.99

La subconsulta correlacionada encuentra la fecha máxima de pedido para cada cliente, y la consulta exterior recupera la fila completa correspondiente. Alternativamente, puedes usar ROW_NUMBER:

SELECT nombre, apellidos, pedido_id, fecha_pedido, total
FROM (
    SELECT
        cl.nombre,
        cl.apellidos,
        p.id AS pedido_id,
        p.fecha_pedido,
        p.total,
        ROW_NUMBER() OVER (
            PARTITION BY cl.id ORDER BY p.fecha_pedido DESC
        ) AS rn
    FROM pedidos p
    JOIN clientes cl ON p.cliente_id = cl.id
) ranked
WHERE rn = 1
ORDER BY fecha_pedido DESC
LIMIT 5;

Caso práctico: MAX con fechas para análisis temporal

MAX con fechas es especialmente útil para calcular métricas de recencia. Veamos cuántos días han pasado desde el último pedido de cada cliente:

SELECT
    cl.nombre,
    cl.apellidos,
    MAX(p.fecha_pedido) AS ultimo_pedido,
    DATEDIFF(CURDATE(), MAX(p.fecha_pedido)) AS dias_sin_comprar
FROM clientes cl
JOIN pedidos p ON cl.id = p.cliente_id
WHERE p.estado = 'completado'
GROUP BY cl.id, cl.nombre, cl.apellidos
HAVING DATEDIFF(CURDATE(), MAX(p.fecha_pedido)) > 90
ORDER BY dias_sin_comprar DESC
LIMIT 5;
nombreapellidosultimo_pedidodias_sin_comprar
RobertoMuñoz Vega2025-06-12247
BeatrizJiménez Soto2025-07-25204
FernandoRuiz Castillo2025-08-10188
SusanaMorales García2025-09-01166
AndrésTorres Luna2025-10-15122

Esta consulta identifica a los clientes inactivos (más de 90 días sin comprar), ordenados por los que llevan más tiempo sin actividad. Es la base de muchas estrategias de reactivación de clientes.

Caso práctico: MAX con cadenas de texto

MAX con cadenas devuelve el último valor en orden alfabético:

SELECT
    c.nombre AS categoria,
    MIN(p.nombre) AS primer_producto_alfa,
    MAX(p.nombre) AS ultimo_producto_alfa
FROM productos p
JOIN categorias c ON p.categoria_id = c.id
GROUP BY c.nombre
ORDER BY c.nombre;
categoriaprimer_producto_alfaultimo_producto_alfa
Accesorios electrónicosCable USB-C a LightningSoporte portátil aluminio
HogarJuego de sábanas algodónVela aromática lavanda
SmartphonesGoogle Pixel 8Xiaomi Redmi Note 13

El orden depende de la intercalación de la columna. Con utf8mb4_general_ci (la predeterminada en muchas configuraciones), las mayúsculas y minúsculas se tratan como iguales.

Manejo de NULL

MAX ignora los valores NULL. Si todas las filas de un grupo tienen NULL, el resultado es NULL:

SELECT
    MAX(descuento) AS mayor_descuento,
    COALESCE(MAX(descuento), 0) AS mayor_o_cero
FROM productos
WHERE categoria_id = 5;
mayor_descuentomayor_o_cero
NULL0

Si ningún libro tiene descuento, MAX devuelve NULL. COALESCE lo convierte en cero para evitar problemas en la aplicación.

Combinación con otras funciones

MAX se usa frecuentemente en HAVING para filtrar grupos según su valor máximo:

SELECT
    c.nombre AS categoria,
    MAX(p.precio) AS precio_maximo
FROM productos p
JOIN categorias c ON p.categoria_id = c.id
GROUP BY c.nombre
HAVING MAX(p.precio) > 500
ORDER BY precio_maximo DESC;
categoriaprecio_maximo
Portátiles1899.99
Smartphones1299.99

Solo Portátiles y Smartphones tienen productos que superan los 500 euros.

Otra combinación útil es con subconsultas para encontrar el máximo global y comparar:

SELECT
    nombre,
    precio,
    ROUND(precio / (SELECT MAX(precio) FROM productos) * 100, 1) AS pct_del_maximo
FROM productos
ORDER BY precio DESC
LIMIT 5;
nombrepreciopct_del_maximo
ASUS ROG Zephyrus1899.99100.0
Lenovo ThinkPad X11549.0081.5
MacBook Air M31399.0073.6
iPhone 15 Pro1299.9968.4
Dell XPS 151249.0065.7

Cada producto se muestra como un porcentaje del precio más alto, lo que da una perspectiva relativa de su posición en el catálogo.

Practica con MAX

Usa el editor para encontrar valores máximos:

Simulador SQL
Ctrl+Enter para ejecutar

En el siguiente artículo veremos GROUP_CONCAT para concatenar valores agrupados.

Escrito por Eduardo Lázaro