Agregación · fechas

Agrupar por mes en SQL: fechas y GROUP BY

Resume pedidos, ventas o eventos por mes sin mezclar años distintos y adapta la clave temporal al motor que utilizas.

Lectura: 8–10 minIntermediaEjemplo comprobado
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

Idea portable
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.

SQLite · ejecutado sobre la base educativa
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;
Resultado comprobado
mespedidosfacturacion
2025-05101976.10
2025-0681955.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.

PostgreSQL
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.

MySQL 8.4
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.

SQL Server 2022+
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

Intermedia · fechas + agregación

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.

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 usar DATE_FORMAT; SQL Server 2022+ ofrece DATETRUNC; SQLite dispone de strftime.
  • 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.

Conceptos relacionados

Fuentes técnicas consultadas