PERIOD_ADD
La función PERIOD_ADD suma un número determinado de meses a un valor de período y devuelve el resultado en formato YYYYMM. Es importante entender que un período en MySQL no es un tipo de dato de fecha, sino un número entero que representa un mes específico de un año en formato YYMM o YYYYMM. Esta distinción es fundamental porque PERIOD_ADD no trabaja con valores DATE ni DATETIME, sino con estos valores numéricos de período.
Los períodos son útiles en contextos financieros y contables donde los cálculos se realizan por mes completo, como ejercicios fiscales, períodos de facturación o trimestres de reporte. Cuando necesitas saber en qué mes-año caerá una fecha futura contando cierta cantidad de meses, PERIOD_ADD ofrece una solución directa sin necesidad de crear objetos de fecha intermedios.
Sintaxis
PERIOD_ADD(P, N)El primer argumento P es el período base en formato YYMM o YYYYMM. El segundo argumento N es el número de meses a sumar, que puede ser positivo para avanzar en el tiempo o negativo para retroceder. El resultado siempre se devuelve en formato YYYYMM, independientemente de si el período de entrada usó dos o cuatro dígitos para el año.
Comportamiento básico
La operación más simple es sumar meses a un período dado.
SELECT
PERIOD_ADD(202602, 3) AS tres_meses_despues,
PERIOD_ADD(202602, 6) AS seis_meses_despues,
PERIOD_ADD(202602, 12) AS un_anio_despues;| tres_meses_despues | seis_meses_despues | un_anio_despues |
|---|---|---|
| 202605 | 202608 | 202702 |
Febrero de 2026 más 3 meses da mayo de 2026, más 6 meses da agosto de 2026 y más 12 meses da febrero de 2027. La función maneja automáticamente el cambio de año.
También puedes usar valores negativos para retroceder en el tiempo.
SELECT
PERIOD_ADD(202602, -1) AS mes_anterior,
PERIOD_ADD(202602, -6) AS seis_meses_antes,
PERIOD_ADD(202602, -24) AS dos_anios_antes;| mes_anterior | seis_meses_antes | dos_anios_antes |
|---|---|---|
| 202601 | 202508 | 202402 |
Si usas el formato de dos dígitos para el año, MySQL lo interpreta y devuelve el resultado con cuatro dígitos.
SELECT
PERIOD_ADD(2602, 3) AS desde_formato_corto,
PERIOD_ADD(9912, 1) AS cambio_de_siglo;| desde_formato_corto | cambio_de_siglo |
|---|---|
| 202605 | 200001 |
MySQL interpreta 26 como 2026 y 99 como 1999, siguiendo las reglas estándar de conversión de años de dos dígitos (00-69 se mapean a 2000-2069, y 70-99 a 1970-1999).
Caso práctico: calcular períodos de facturación
Una empresa de suscripciones necesita calcular cuándo vencerá cada período de facturación según la duración del plan contratado.
SELECT
c.nombre AS cliente,
c.plan,
c.periodo_inicio,
CASE c.plan
WHEN 'Mensual' THEN PERIOD_ADD(c.periodo_inicio, 1)
WHEN 'Trimestral' THEN PERIOD_ADD(c.periodo_inicio, 3)
WHEN 'Semestral' THEN PERIOD_ADD(c.periodo_inicio, 6)
WHEN 'Anual' THEN PERIOD_ADD(c.periodo_inicio, 12)
END AS periodo_vencimiento
FROM clientes_suscripcion c
ORDER BY c.periodo_inicio;| cliente | plan | periodo_inicio | periodo_vencimiento |
|---|---|---|---|
| María García | Mensual | 202602 | 202603 |
| Carlos López | Trimestral | 202601 | 202604 |
| Laura Sánchez | Semestral | 202601 | 202607 |
| Pedro Fernández | Anual | 202601 | 202701 |
De esta forma, con una sola expresión CASE combinada con PERIOD_ADD, se calcula el vencimiento para cualquier tipo de plan sin necesidad de convertir a fechas.
Caso práctico: proyección de períodos fiscales
Una empresa con año fiscal que comienza en abril necesita generar los 12 períodos de su ejercicio fiscal a partir del mes de inicio.
SELECT
n.num AS numero_periodo,
PERIOD_ADD(202604, n.num - 1) AS periodo_fiscal,
CONCAT('Q', CEIL(n.num / 3)) AS trimestre
FROM (
SELECT 1 AS num UNION ALL SELECT 2 UNION ALL SELECT 3
UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12
) n;| numero_periodo | periodo_fiscal | trimestre |
|---|---|---|
| 1 | 202604 | Q1 |
| 2 | 202605 | Q1 |
| 3 | 202606 | Q1 |
| 4 | 202607 | Q2 |
| 5 | 202608 | Q2 |
| 6 | 202609 | Q2 |
| 7 | 202610 | Q3 |
| 8 | 202611 | Q3 |
| 9 | 202612 | Q3 |
| 10 | 202701 | Q4 |
| 11 | 202702 | Q4 |
| 12 | 202703 | Q4 |
Este enfoque genera todos los períodos del año fiscal a partir de un solo punto de partida, lo que facilita la creación de plantillas de presupuesto o calendarios de cierre contable.
Caso práctico: histórico de pagos mensuales
Un sistema de créditos necesita verificar si un cliente ha realizado todos sus pagos mensuales comparando el período esperado con los períodos efectivamente pagados.
SELECT
PERIOD_ADD(c.periodo_inicio_credito, p.numero_cuota) AS periodo_esperado,
p.numero_cuota,
p.monto_cuota,
p.periodo_pago,
CASE
WHEN p.periodo_pago IS NULL THEN 'Pendiente'
WHEN p.periodo_pago = PERIOD_ADD(c.periodo_inicio_credito, p.numero_cuota) THEN 'A tiempo'
WHEN p.periodo_pago > PERIOD_ADD(c.periodo_inicio_credito, p.numero_cuota) THEN 'Atrasado'
ELSE 'Adelantado'
END AS estado
FROM creditos c
JOIN pagos_credito p ON c.id = p.credito_id
WHERE c.cliente_id = 1042
ORDER BY p.numero_cuota
LIMIT 6;| periodo_esperado | numero_cuota | monto_cuota | periodo_pago | estado |
|---|---|---|---|---|
| 202610 | 1 | 850.00 | 202610 | A tiempo |
| 202611 | 2 | 850.00 | 202611 | A tiempo |
| 202612 | 3 | 850.00 | 202701 | Atrasado |
| 202701 | 4 | 850.00 | 202701 | A tiempo |
| 202702 | 5 | 850.00 | NULL | Pendiente |
| 202703 | 6 | 850.00 | NULL | Pendiente |
Diferencia con DATE_ADD
Es importante no confundir PERIOD_ADD con DATE_ADD. Mientras que DATE_ADD trabaja con valores DATE o DATETIME y puede sumar días, horas, semanas y otros intervalos además de meses, PERIOD_ADD trabaja exclusivamente con períodos numéricos y solo suma meses.
-- DATE_ADD trabaja con fechas completas
SELECT DATE_ADD('2026-02-14', INTERVAL 3 MONTH) AS con_date_add;
-- PERIOD_ADD trabaja con períodos numéricos
SELECT PERIOD_ADD(202602, 3) AS con_period_add;| con_date_add |
|---|
| 2026-05-14 |
| con_period_add |
|---|
| 202605 |
DATE_ADD preserva el día específico del mes (14 de mayo), mientras que PERIOD_ADD solo indica el mes y el año (mayo de 2026). Usa PERIOD_ADD cuando trabajas con datos que naturalmente se representan por mes, como períodos contables o fechas de facturación mensual.
Manejo de NULL
PERIOD_ADD devuelve NULL si cualquiera de sus argumentos es NULL.
SELECT
PERIOD_ADD(NULL, 3) AS periodo_nulo,
PERIOD_ADD(202602, NULL) AS meses_nulo;| periodo_nulo | meses_nulo |
|---|---|
| NULL | NULL |
Cuando trabajas con columnas que pueden contener valores nulos, protege la expresión con IFNULL o COALESCE.
SELECT
nombre,
COALESCE(
PERIOD_ADD(periodo_inicio, duracion_meses),
0
) AS periodo_fin
FROM contratos
WHERE activo = 1;| nombre | periodo_fin |
|---|---|
| Contrato A-2026 | 202608 |
| Contrato B-2026 | 202612 |
| Contrato temporal | 0 |
Combinación con otras funciones
PERIOD_ADD se combina naturalmente con PERIOD_DIFF para realizar cálculos completos de períodos. También puedes convertir un período a una fecha real concatenando 01 como día y usando STR_TO_DATE.
SELECT
PERIOD_ADD(202602, 6) AS periodo_resultado,
STR_TO_DATE(
CONCAT(PERIOD_ADD(202602, 6), '01'),
'%Y%m%d'
) AS como_fecha,
LAST_DAY(
STR_TO_DATE(CONCAT(PERIOD_ADD(202602, 6), '01'), '%Y%m%d')
) AS ultimo_dia_del_mes;| periodo_resultado | como_fecha | ultimo_dia_del_mes |
|---|---|---|
| 202608 | 2026-08-01 | 2026-08-31 |
Esta conversión es útil cuando necesitas pasar de un cálculo basado en períodos a una fecha concreta para combinar con otras funciones de fecha de MySQL.
Para extraer el año y el mes de un período de forma numérica, puedes usar divisiones y módulo.
SELECT
202608 AS periodo,
202608 DIV 100 AS anio,
202608 MOD 100 AS mes;| periodo | anio | mes |
|---|---|---|
| 202608 | 2026 | 8 |
En el siguiente artículo veremos PERIOD_DIFF para calcular la diferencia en meses entre dos períodos.
Escrito por Eduardo Lázaro
