MIN

La función MIN devuelve el valor más pequeño de un conjunto de valores. Aunque parece una función trivial, tiene usos muy variados: encontrar el producto más barato, la fecha del primer pedido, el empleado con menor antigüedad o incluso el primer valor alfabéticamente en una columna de texto. Al igual que las demás funciones de agregación, MIN ignora los valores NULL.

Sintaxis

MIN(expresion)

MIN acepta una columna o cualquier expresión que devuelva un valor comparable. Funciona con números, fechas, cadenas de texto y cualquier tipo de dato que MySQL pueda ordenar. Cuando se usa sin GROUP BY, devuelve el valor mínimo de toda la tabla. Con GROUP BY, devuelve el mínimo de cada grupo.

Comportamiento básico

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

SELECT
    MIN(precio) AS precio_minimo,
    MAX(precio) AS precio_maximo,
    MAX(precio) - MIN(precio) AS rango_precios
FROM productos;
precio_minimoprecio_maximorango_precios
9.991899.991890.00

El rango de precios (la diferencia entre el máximo y el mínimo) te da una idea de la dispersión del catálogo. Un rango de 1890 euros indica que el inventario abarca desde accesorios económicos hasta equipos de alta gama.

MIN también funciona con fechas. Para saber cuándo se registró el primer pedido:

SELECT
    MIN(fecha_pedido) AS primer_pedido,
    MAX(fecha_pedido) AS ultimo_pedido,
    DATEDIFF(MAX(fecha_pedido), MIN(fecha_pedido)) AS dias_operacion
FROM pedidos;
primer_pedidoultimo_pedidodias_operacion
2024-03-152026-02-10697

La tienda lleva 697 días de operación, desde marzo de 2024 hasta febrero de 2026.

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

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

SELECT
    c.nombre AS categoria,
    MIN(p.precio) AS precio_minimo,
    ROUND(AVG(p.precio), 2) AS precio_medio
FROM productos p
JOIN categorias c ON p.categoria_id = c.id
GROUP BY c.nombre
ORDER BY precio_minimo ASC;
categoriaprecio_minimoprecio_medio
Accesorios electrónicos9.9942.85
Libros14.9922.50
Ropa hombre19.9959.99
Ropa mujer24.9964.99
Hogar29.99124.80
Deportes39.99189.99
Smartphones299.00785.42
Portátiles799.001245.50

Observa que en algunas categorías el precio mínimo está muy lejos de la media. Los accesorios van desde 9.99 hasta precios más altos, mientras que los portátiles empiezan en 799 euros.

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

Un problema clásico: no solo quieres saber cuál es el precio mínimo, sino qué producto tiene ese precio. MIN devuelve solo el valor, no la fila completa. Hay varias formas de resolverlo.

La más directa es usar una subconsulta:

SELECT nombre, precio
FROM productos
WHERE precio = (SELECT MIN(precio) FROM productos);
nombreprecio
Cable USB-C a Lightning9.99

Si quieres el producto más barato de cada categoría, necesitas una subconsulta correlacionada o un JOIN:

SELECT p.nombre, c.nombre AS categoria, p.precio
FROM productos p
JOIN categorias c ON p.categoria_id = c.id
WHERE p.precio = (
    SELECT MIN(p2.precio)
    FROM productos p2
    WHERE p2.categoria_id = p.categoria_id
)
ORDER BY p.precio;
nombrecategoriaprecio
Cable USB-C a LightningAccesorios electrónicos9.99
El Quijote edición bolsilloLibros14.99
Camiseta algodón básicaRopa hombre19.99
Blusa estampadaRopa mujer24.99
Vela aromática lavandaHogar29.99
Banda de resistenciaDeportes39.99
Xiaomi Redmi Note 13Smartphones299.00
Acer Aspire 5Portátiles799.00

Otra alternativa moderna es usar la función de ventana ROW_NUMBER:

SELECT nombre, categoria, precio
FROM (
    SELECT
        p.nombre,
        c.nombre AS categoria,
        p.precio,
        ROW_NUMBER() OVER (PARTITION BY c.id ORDER BY p.precio ASC) AS rn
    FROM productos p
    JOIN categorias c ON p.categoria_id = c.id
) ranked
WHERE rn = 1
ORDER BY precio;

Este enfoque es más eficiente cuando tienes muchas categorías porque evita ejecutar una subconsulta por cada fila.

Caso práctico: MIN con cadenas de texto

MIN aplicado a cadenas de texto devuelve el primer valor en orden alfabético según la intercalación (collation) de la columna:

SELECT
    MIN(nombre) AS primer_nombre_alfa,
    MAX(nombre) AS ultimo_nombre_alfa
FROM clientes;
primer_nombre_alfaultimo_nombre_alfa
AlbertoVíctor

Esto es útil para verificar rangos de datos o para consultas donde necesitas el primer o último valor lexicográfico de un grupo.

Manejo de NULL

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

SELECT
    MIN(descuento) AS menor_descuento,
    MIN(IFNULL(descuento, 0)) AS menor_con_ceros
FROM productos;
menor_descuentomenor_con_ceros
5.000

Sin IFNULL, el menor descuento registrado es 5.00, porque los productos sin descuento (NULL) se ignoran. Con IFNULL, los NULL se convierten en cero y el mínimo pasa a ser 0. Elige uno u otro según el contexto de tu análisis.

Combinación con otras funciones

MIN se combina frecuentemente con otras funciones de agregación para crear resúmenes estadísticos completos:

SELECT
    c.nombre AS categoria,
    COUNT(*) AS productos,
    MIN(p.precio) AS minimo,
    ROUND(AVG(p.precio), 2) AS media,
    MAX(p.precio) AS maximo,
    MAX(p.precio) - MIN(p.precio) AS rango
FROM productos p
JOIN categorias c ON p.categoria_id = c.id
GROUP BY c.nombre
ORDER BY rango DESC;
categoriaproductosminimomediamaximorango
Portátiles8799.001245.501899.991100.99
Smartphones12299.00785.421299.991000.99
Deportes439.99189.99449.99410.00
Hogar529.99124.80299.99270.00

El rango (diferencia entre máximo y mínimo) indica cuán variados son los precios dentro de cada categoría. Un rango alto sugiere que la categoría cubre diferentes segmentos de mercado.

También puedes usar MIN en HAVING para filtrar grupos:

SELECT c.nombre AS categoria
FROM productos p
JOIN categorias c ON p.categoria_id = c.id
GROUP BY c.nombre
HAVING MIN(p.precio) > 100;

Esta consulta encuentra las categorías donde incluso el producto más barato cuesta más de 100 euros.

Practica con MIN

Usa el editor para encontrar valores mínimos:

Simulador SQL
Ctrl+Enter para ejecutar

En el siguiente artículo veremos MAX para obtener el valor máximo.

Escrito por Eduardo Lázaro