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_despuesseis_meses_despuesun_anio_despues
202605202608202702

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_anteriorseis_meses_antesdos_anios_antes
202601202508202402

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_cortocambio_de_siglo
202605200001

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;
clienteplanperiodo_inicioperiodo_vencimiento
María GarcíaMensual202602202603
Carlos LópezTrimestral202601202604
Laura SánchezSemestral202601202607
Pedro FernándezAnual202601202701

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_periodoperiodo_fiscaltrimestre
1202604Q1
2202605Q1
3202606Q1
4202607Q2
5202608Q2
6202609Q2
7202610Q3
8202611Q3
9202612Q3
10202701Q4
11202702Q4
12202703Q4

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_esperadonumero_cuotamonto_cuotaperiodo_pagoestado
2026101850.00202610A tiempo
2026112850.00202611A tiempo
2026123850.00202701Atrasado
2027014850.00202701A tiempo
2027025850.00NULLPendiente
2027036850.00NULLPendiente

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_nulomeses_nulo
NULLNULL

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;
nombreperiodo_fin
Contrato A-2026202608
Contrato B-2026202612
Contrato temporal0

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_resultadocomo_fechaultimo_dia_del_mes
2026082026-08-012026-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;
periodoaniomes
20260820268

En el siguiente artículo veremos PERIOD_DIFF para calcular la diferencia en meses entre dos períodos.

Escrito por Eduardo Lázaro