Contenido de esta guía
La idea: convertir cada fecha en una clave mensual
Para agrupar por mes necesitas transformar cada fecha en una clave que identifique el mes y el año. Después, GROUP BY reúne todas las filas que comparten esa clave y las funciones de agregación calculan el resumen.
La trampa más común es agrupar solo por el número de mes. Si usas únicamente enero = 1, las filas de enero de 2025 y enero de 2026 terminan en el mismo grupo. Por eso la clave debe conservar al menos año + mes.
Patrón general
SELECT clave_mes(fecha) AS mes,
COUNT(*) AS filas,
SUM(importe) AS total
FROM tabla
GROUP BY clave_mes(fecha)
ORDER BY mes;clave_mes(fecha) no es una función SQL real: representa la operación que cambia según el dialecto. Lo importante es que la misma expresión identifique de forma estable cada periodo mensual.
Ejemplo comprobado con pedidos
La base educativa contiene 18 pedidos entre mayo y junio de 2025. En SQLite podemos convertir fecha al formato YYYY-MM con strftime() y agrupar por ese valor.
SELECT strftime('%Y-%m', fecha) AS mes,
COUNT(*) AS pedidos,
ROUND(SUM(total), 2) AS facturacion
FROM pedidos
GROUP BY strftime('%Y-%m', fecha)
ORDER BY mes;| mes | pedidos | facturacion |
|---|---|---|
| 2025-05 | 10 | 1976.10 |
| 2025-06 | 8 | 1955.80 |
La consulta produce una fila por mes. COUNT(*) cuenta pedidos y SUM(total) suma su importe. El ORDER BY mes funciona cronológicamente porque la clave usa año de cuatro dígitos seguido de mes de dos dígitos.
Cómo cambia entre motores
PostgreSQL: date_trunc
PostgreSQL permite truncar un timestamp a una precisión concreta. Con date_trunc('month', fecha), todas las fechas de un mismo mes se convierten en el inicio de ese mes, lo que forma una clave temporal natural.
SELECT date_trunc('month', fecha) AS mes,
COUNT(*) AS pedidos,
SUM(total) AS facturacion
FROM pedidos
GROUP BY date_trunc('month', fecha)
ORDER BY mes;MySQL: DATE_FORMAT
MySQL puede formar una clave de texto YYYY-MM con DATE_FORMAT. También ofrece EXTRACT para obtener año y mes por separado. Mantén ambos componentes si los datos abarcan más de un año.
SELECT DATE_FORMAT(fecha, '%Y-%m') AS mes,
COUNT(*) AS pedidos,
SUM(total) AS facturacion
FROM pedidos
GROUP BY DATE_FORMAT(fecha, '%Y-%m')
ORDER BY mes;SQL Server 2022+: DATETRUNC
SQL Server 2022 introdujo DATETRUNC. DATETRUNC(month, fecha) devuelve la fecha truncada al comienzo del mes. En versiones anteriores puedes agrupar por YEAR(fecha) y MONTH(fecha) como dos claves separadas.
SELECT DATETRUNC(month, fecha) AS mes,
COUNT(*) AS pedidos,
SUM(total) AS facturacion
FROM pedidos
GROUP BY DATETRUNC(month, fecha)
ORDER BY mes;SQLite: strftime
SQLite no tiene un tipo fecha/hora dedicado ni date_trunc. Para fechas ISO como las de la base educativa, strftime('%Y-%m', fecha) crea una clave mensual legible y ordenable.
Errores frecuentes
Agrupar solo por el número de mes
-- Problema si existen varios años
GROUP BY EXTRACT(MONTH FROM fecha)Esta expresión mezcla, por ejemplo, enero de 2025 con enero de 2026. Incluye el año en la clave o usa una función que trunque la fecha al mes completo.
Mostrar un texto bonito antes de definir la clave correcta
El formato de presentación y la clave de agrupación no son exactamente el mismo problema. Primero garantiza que el periodo sea inequívoco y cronológico; después decide si quieres mostrar 2025-06, junio 2025 u otra etiqueta.
Ignorar zona horaria en timestamps
Si almacenas instantes con zona horaria, una venta cercana a medianoche puede pertenecer a meses distintos según la zona con la que interpretes el dato. Define la zona de negocio antes de truncar o formatear el timestamp.
Comprueba lo aprendido
Cuenta pedidos por mes en SQLite
Devuelve mes, pedidos y facturacion usando la tabla pedidos. El mes debe quedar en formato YYYY-MM y los resultados deben ordenarse cronológicamente.
Criterio de éxito: no agrupas solo por el número de mes, cuentas todas las filas y sumas total.
strftime('%Y-%m', fecha) conserva año y mes.SELECT y GROUP BY.COUNT(*) con SUM(total) y ordena por la clave mensual.Solución razonada
SELECT strftime('%Y-%m', fecha) AS mes,
COUNT(*) AS pedidos,
ROUND(SUM(total), 2) AS facturacion
FROM pedidos
GROUP BY strftime('%Y-%m', fecha)
ORDER BY mes;La expresión %Y-%m evita mezclar años. Una vez formada la clave, GROUP BY cambia la unidad de análisis: de una fila por pedido a una fila por mes.
Qué debes recordar
- Agrupar por mes significa construir una clave que represente año + mes.
- Agrupar solo por el número de mes mezcla años distintos.
- PostgreSQL usa
date_trunc; MySQL puede usarDATE_FORMAT; SQL Server 2022+ ofreceDATETRUNC; SQLite dispone destrftime. - La función cambia entre motores, pero el modelo mental es el mismo: convertir fecha → periodo → agregar.
- Con timestamps, define primero qué zona horaria determina el mes de negocio.