MONTH
La función MONTH extrae el número de mes de una fecha y lo devuelve como un entero entre 1 y 12. Enero es 1, febrero es 2 y así sucesivamente hasta diciembre que es 12. Es una de las funciones de fecha más utilizadas en MySQL porque los informes mensuales son la base de prácticamente cualquier análisis empresarial.
Mientras que YEAR te da la visión macro del negocio, MONTH te permite ver los patrones estacionales: qué meses venden más, cuándo bajan las contrataciones, en qué época del año los clientes compran cierto tipo de producto. Todo ese análisis empieza extrayendo el mes de una fecha.
Sintaxis
MONTH(fecha)El argumento fecha acepta valores de tipo DATE, DATETIME, TIMESTAMP o una cadena con formato de fecha válido. Devuelve un entero de 1 a 12. Si la fecha es '0000-00-00', devuelve 0.
Comportamiento básico
MONTH toma cualquier fecha y devuelve su componente de mes como un número simple:
SELECT
MONTH('2025-01-15') AS enero,
MONTH('2025-06-20') AS junio,
MONTH('2025-12-31') AS diciembre,
MONTH(NOW()) AS mes_actual;| enero | junio | diciembre | mes_actual |
|---|---|---|---|
| 1 | 6 | 12 | 2 |
El resultado es siempre un entero sin ceros a la izquierda. Enero es 1, no "01". Si necesitas el nombre del mes en lugar del número, MySQL ofrece la función MONTHNAME() que devuelve el nombre en el idioma configurado.
Aplicar MONTH a una columna
El uso típico es extraer el mes de una columna de fecha en tus consultas:
SELECT
nombre,
fecha_pedido,
MONTH(fecha_pedido) AS mes_pedido
FROM pedidos
ORDER BY fecha_pedido
LIMIT 5;| nombre | fecha_pedido | mes_pedido |
|---|---|---|
| Pedido #4010 | 2024-01-03 | 1 |
| Pedido #4011 | 2024-01-05 | 1 |
| Pedido #4012 | 2024-01-07 | 1 |
| Pedido #4013 | 2024-02-01 | 2 |
| Pedido #4014 | 2024-02-04 | 2 |
Caso práctico: informe mensual de ventas
El escenario más común para MONTH es generar informes mensuales. Agrupando por mes puedes ver cómo evolucionan las ventas a lo largo del año:
SELECT
MONTH(fecha_venta) AS mes,
COUNT(*) AS num_ventas,
SUM(total) AS ingresos,
ROUND(AVG(total), 2) AS ticket_medio
FROM ventas
WHERE YEAR(fecha_venta) = 2024
GROUP BY MONTH(fecha_venta)
ORDER BY mes;| mes | num_ventas | ingresos | ticket_medio |
|---|---|---|---|
| 1 | 380 | 57000.00 | 150.00 |
| 2 | 345 | 51750.00 | 150.00 |
| 3 | 410 | 65600.00 | 160.00 |
| 4 | 425 | 72250.00 | 170.00 |
| 5 | 398 | 67660.00 | 170.00 |
| 6 | 440 | 79200.00 | 180.00 |
| 7 | 370 | 62900.00 | 170.00 |
| 8 | 355 | 60350.00 | 170.00 |
| 9 | 415 | 70550.00 | 170.00 |
| 10 | 450 | 81000.00 | 180.00 |
| 11 | 478 | 86040.00 | 180.00 |
| 12 | 520 | 98800.00 | 190.00 |
De esta tabla puedes detectar que las ventas suben considerablemente en el último trimestre (octubre a diciembre), probablemente por las campañas de fin de año. Julio y agosto muestran un bajón típico del periodo vacacional.
Caso práctico: análisis estacional con agrupación por año y mes
Cuando necesitas comparar el mismo mes entre distintos años, combina YEAR y MONTH en el GROUP BY:
SELECT
YEAR(fecha_venta) AS anio,
MONTH(fecha_venta) AS mes,
SUM(total) AS ingresos
FROM ventas
WHERE MONTH(fecha_venta) IN (11, 12)
AND YEAR(fecha_venta) >= 2022
GROUP BY YEAR(fecha_venta), MONTH(fecha_venta)
ORDER BY anio, mes;| anio | mes | ingresos |
|---|---|---|
| 2022 | 11 | 68500.00 |
| 2022 | 12 | 82300.00 |
| 2023 | 11 | 76200.00 |
| 2023 | 12 | 91500.00 |
| 2024 | 11 | 86040.00 |
| 2024 | 12 | 98800.00 |
Este análisis revela que noviembre y diciembre crecen consistentemente año tras año. El filtro MONTH(fecha_venta) IN (11, 12) selecciona solo esos dos meses, y al agrupar también por YEAR puedes ver la tendencia histórica.
Caso práctico: categorizar meses por temporada
Puedes usar MONTH dentro de una expresión CASE para agrupar meses en categorías de negocio como temporadas:
SELECT
CASE
WHEN MONTH(fecha_venta) IN (12, 1, 2) THEN 'Invierno'
WHEN MONTH(fecha_venta) IN (3, 4, 5) THEN 'Primavera'
WHEN MONTH(fecha_venta) IN (6, 7, 8) THEN 'Verano'
WHEN MONTH(fecha_venta) IN (9, 10, 11) THEN 'Otoño'
END AS temporada,
COUNT(*) AS num_ventas,
SUM(total) AS ingresos,
ROUND(AVG(total), 2) AS ticket_medio
FROM ventas
WHERE YEAR(fecha_venta) = 2024
GROUP BY
CASE
WHEN MONTH(fecha_venta) IN (12, 1, 2) THEN 'Invierno'
WHEN MONTH(fecha_venta) IN (3, 4, 5) THEN 'Primavera'
WHEN MONTH(fecha_venta) IN (6, 7, 8) THEN 'Verano'
WHEN MONTH(fecha_venta) IN (9, 10, 11) THEN 'Otoño'
END
ORDER BY ingresos DESC;| temporada | num_ventas | ingresos | ticket_medio |
|---|---|---|---|
| Otoño | 1343 | 237590.00 | 176.91 |
| Invierno | 1245 | 207550.00 | 166.67 |
| Primavera | 1233 | 205510.00 | 166.68 |
| Verano | 1165 | 202450.00 | 173.78 |
Este enfoque es más informativo que mostrar 12 filas individuales cuando lo que importa es la tendencia estacional. El CASE convierte los números de mes en etiquetas comprensibles que cualquier persona de negocio puede interpretar sin pensar qué mes es el 3 o el 9.
Caso práctico: tabla pivotada mes a mes
Un patrón avanzado pero muy útil es pivotar los datos mensuales en columnas usando MONTH dentro de expresiones CASE:
SELECT
categoria,
SUM(CASE WHEN MONTH(fecha_venta) = 1 THEN total ELSE 0 END) AS ene,
SUM(CASE WHEN MONTH(fecha_venta) = 2 THEN total ELSE 0 END) AS feb,
SUM(CASE WHEN MONTH(fecha_venta) = 3 THEN total ELSE 0 END) AS mar,
SUM(CASE WHEN MONTH(fecha_venta) = 4 THEN total ELSE 0 END) AS abr,
SUM(CASE WHEN MONTH(fecha_venta) = 5 THEN total ELSE 0 END) AS may,
SUM(CASE WHEN MONTH(fecha_venta) = 6 THEN total ELSE 0 END) AS jun
FROM ventas
JOIN productos USING (id_producto)
WHERE YEAR(fecha_venta) = 2024
GROUP BY categoria;| categoria | ene | feb | mar | abr | may | jun |
|---|---|---|---|---|---|---|
| Electrónica | 18500.00 | 16200.00 | 21300.00 | 23400.00 | 19800.00 | 25100.00 |
| Ropa | 12300.00 | 11500.00 | 14800.00 | 16200.00 | 15600.00 | 18700.00 |
| Alimentación | 26200.00 | 24050.00 | 29500.00 | 32650.00 | 32260.00 | 35400.00 |
Esta tabla cruzada es el formato que suelen pedir los informes de gestión. Cada fila es una categoría y cada columna un mes, lo que facilita la comparación visual.
MONTH con NULL
MONTH devuelve NULL cuando la entrada es NULL:
SELECT
MONTH(NULL) AS resultado,
MONTH('0000-00-00') AS fecha_cero;| resultado | fecha_cero |
|---|---|
| NULL | 0 |
Al igual que YEAR, una fecha '0000-00-00' devuelve 0 en lugar de NULL. Si tu tabla puede contener este tipo de valores, filtra con WHERE fecha IS NOT NULL AND fecha != '0000-00-00' para evitar resultados inesperados en tus agrupaciones.
Combinación con otras funciones
MONTH se combina especialmente bien con MONTHNAME para añadir etiquetas legibles y con LPAD para formatear el número con cero a la izquierda:
SELECT
MONTH(fecha_venta) AS num_mes,
MONTHNAME(fecha_venta) AS nombre_mes,
LPAD(MONTH(fecha_venta), 2, '0') AS mes_formateado,
CONCAT(YEAR(fecha_venta), '-', LPAD(MONTH(fecha_venta), 2, '0')) AS periodo,
COUNT(*) AS ventas
FROM ventas
WHERE YEAR(fecha_venta) = 2024
GROUP BY
MONTH(fecha_venta),
MONTHNAME(fecha_venta),
YEAR(fecha_venta)
ORDER BY num_mes
LIMIT 4;| num_mes | nombre_mes | mes_formateado | periodo | ventas |
|---|---|---|---|---|
| 1 | January | 01 | 2024-01 | 380 |
| 2 | February | 02 | 2024-02 | 345 |
| 3 | March | 03 | 2024-03 | 410 |
| 4 | April | 04 | 2024-04 | 425 |
Nota que MONTHNAME devuelve el nombre en inglés por defecto. Si quieres que aparezca en español, necesitas configurar la variable lc_time_names con SET lc_time_names = 'es_ES' antes de ejecutar la consulta.
En el siguiente artículo veremos DAY para extraer el día del mes.
Escrito por Eduardo Lázaro
