WEEK

La funcion WEEK() devuelve el numero de semana del ano para una fecha dada. Lo que hace especial a esta funcion es su segundo parametro mode, que permite controlar como se calcula la primera semana del ano y si la semana empieza en domingo o en lunes. Comprender este parametro es esencial para generar reportes semanales precisos, especialmente en entornos internacionales donde las convenciones sobre semanas varian entre paises.

Sintaxis

WEEK(fecha)
WEEK(fecha, modo)

El parametro fecha acepta valores de tipo DATE o DATETIME. El parametro modo es opcional y acepta valores del 0 al 7. Si omites el modo, MySQL usa el valor de la variable del sistema default_week_format, que por defecto es 0.

Cada modo define dos cosas: que dia se considera el inicio de la semana y como se determina la primera semana del ano. La siguiente tabla resume los ocho modos disponibles:

ModoPrimer diaRangoPrimera semana es...
0Domingo0-53La que tiene un domingo en este ano
1Lunes0-53La que tiene 4 o mas dias en este ano
2Domingo1-53La que tiene un domingo en este ano
3Lunes1-53La que tiene 4 o mas dias en este ano (ISO)
4Domingo0-53La que tiene 4 o mas dias en este ano
5Lunes0-53La que tiene un lunes en este ano
6Domingo1-53La que tiene 4 o mas dias en este ano
7Lunes1-53La que tiene un lunes en este ano

La diferencia entre modos con rango 0-53 y 1-53 es importante. En los modos con rango 0-53, los dias al inicio del ano que caen antes de la primera semana completa se asignan a la semana 0. En los modos con rango 1-53, esos mismos dias se asignan a la ultima semana del ano anterior.

Comportamiento basico

Sin especificar modo (usa modo 0 por defecto), la semana empieza en domingo:

SELECT
    WEEK('2026-01-01') AS semana_1_enero,
    WEEK('2026-01-04') AS semana_4_enero,
    WEEK('2026-02-14') AS semana_14_feb;
semana_1_enerosemana_4_enerosemana_14_feb
016

El 1 de enero de 2026 es jueves. En modo 0 (semanas que empiezan en domingo), como no hay domingo antes del 1 de enero en esa semana, se asigna a la semana 0. El primer domingo del ano es el 4 de enero, que inicia la semana 1.

Comparemos como cambia el resultado segun el modo para la misma fecha:

SELECT
    WEEK('2026-01-01', 0) AS modo_0,
    WEEK('2026-01-01', 1) AS modo_1,
    WEEK('2026-01-01', 2) AS modo_2,
    WEEK('2026-01-01', 3) AS modo_3;
modo_0modo_1modo_2modo_3
01521

El mismo dia puede pertenecer a la semana 0, 1 o incluso 52 dependiendo del modo elegido. Esto demuestra la importancia de ser consistente con el modo que eliges en tus reportes.

Caso practico: reporte semanal de ventas

El uso mas comun de WEEK() es agrupar datos por semana para reportes periodicos:

SELECT
    WEEK(fecha_pedido, 1) AS semana,
    MIN(fecha_pedido) AS desde,
    MAX(fecha_pedido) AS hasta,
    COUNT(*) AS total_pedidos,
    ROUND(SUM(total), 2) AS ingresos
FROM pedidos
WHERE fecha_pedido BETWEEN '2026-01-01' AND '2026-02-14'
GROUP BY WEEK(fecha_pedido, 1)
ORDER BY semana;
semanadesdehastatotal_pedidosingresos
12026-01-012026-01-04286850.30
22026-01-052026-01-115213200.50
32026-01-122026-01-184812100.80
42026-01-192026-01-255514350.20
52026-01-262026-02-015112800.40
62026-02-022026-02-084711650.30
72026-02-092026-02-144611189.00

Se usa el modo 1 para que la semana empiece en lunes, que es la convencion habitual en el ambito empresarial en Espana y Latinoamerica. Las columnas desde y hasta muestran el rango real de fechas en cada semana, lo que hace el reporte mas comprensible.

Caso practico: semanas ISO con modo 3

El estandar ISO 8601 define que la semana empieza en lunes y la primera semana del ano es aquella que contiene el primer jueves del ano (o equivalentemente, la que tiene 4 o mas dias en el nuevo ano). El modo 3 implementa exactamente esta convencion:

SELECT
    fecha,
    WEEK(fecha, 3) AS semana_iso,
    WEEKDAY(fecha) AS dia_semana
FROM (
    SELECT '2025-12-29' AS fecha
    UNION SELECT '2025-12-30'
    UNION SELECT '2025-12-31'
    UNION SELECT '2026-01-01'
    UNION SELECT '2026-01-02'
    UNION SELECT '2026-01-03'
    UNION SELECT '2026-01-04'
) fechas
ORDER BY fecha;
fechasemana_isodia_semana
2025-12-2910
2025-12-3011
2025-12-3112
2026-01-0113
2026-01-0214
2026-01-0315
2026-01-0416

En el estandar ISO, los dias 29, 30 y 31 de diciembre de 2025 ya pertenecen a la semana 1 de 2026 porque esa semana tiene su jueves (1 de enero) en 2026. Esto es importante en contextos internacionales, contabilidad y sistemas que siguen el estandar ISO.

Caso practico: comparar semanas entre anos

Para comparar la semana actual con la misma semana del ano anterior:

SELECT
    YEAR(fecha_pedido) AS ano,
    WEEK(fecha_pedido, 1) AS semana,
    COUNT(*) AS pedidos,
    ROUND(SUM(total), 2) AS ingresos
FROM pedidos
WHERE WEEK(fecha_pedido, 1) = WEEK(CURDATE(), 1)
    AND YEAR(fecha_pedido) IN (2025, 2026)
GROUP BY YEAR(fecha_pedido), WEEK(fecha_pedido, 1)
ORDER BY ano;
anosemanapedidosingresos
202574210350.80
202674611189.00

Esta comparacion semana a semana es mas justa que comparar por fechas exactas, porque la semana 7 de cada ano puede caer en dias ligeramente diferentes pero representa el mismo periodo relativo.

Manejo de NULL

WEEK() devuelve NULL cuando la fecha es nula o invalida:

SELECT
    WEEK(NULL) AS resultado_null,
    WEEK('2025-02-30') AS fecha_invalida,
    WEEK('0000-00-00') AS fecha_cero;
resultado_nullfecha_invalidafecha_cero
NULLNULLNULL

En consultas que operan sobre columnas con posibles valores nulos, asegurate de filtrarlos o manejarlos con COALESCE:

SELECT
    nombre,
    COALESCE(WEEK(fecha_baja, 1), -1) AS semana_baja
FROM empleados;

Combinacion con otras funciones

WEEK() se combina frecuentemente con YEAR() para evitar ambiguedades cuando tus datos abarcan multiples anos. La semana 1 sin el ano podria referirse a enero de 2025 o de 2026:

SELECT
    YEAR(fecha_pedido) AS ano,
    WEEK(fecha_pedido, 1) AS semana,
    COUNT(*) AS pedidos,
    ROUND(SUM(total), 2) AS ingresos
FROM pedidos
WHERE fecha_pedido >= '2025-12-01'
GROUP BY YEAR(fecha_pedido), WEEK(fecha_pedido, 1)
ORDER BY ano, semana
LIMIT 8;
anosemanapedidosingresos
2025494812400.30
2025505214200.50
2025515615800.80
2025525816200.40
20261286850.30
202625213200.50
202634812100.80
202645514350.20

Si necesitas un identificador unico que combine ano y semana en un solo valor, la funcion YEARWEEK() es la solucion ideal para ese caso. Tambien puedes usar CONCAT para construir etiquetas legibles:

SELECT
    CONCAT('S', LPAD(WEEK(fecha_pedido, 1), 2, '0'), '-', YEAR(fecha_pedido)) AS etiqueta,
    COUNT(*) AS pedidos
FROM pedidos
WHERE fecha_pedido BETWEEN '2026-01-01' AND '2026-01-31'
GROUP BY YEAR(fecha_pedido), WEEK(fecha_pedido, 1)
ORDER BY YEAR(fecha_pedido), WEEK(fecha_pedido, 1);
etiquetapedidos
S01-202628
S02-202652
S03-202648
S04-202655

En el siguiente articulo veremos WEEKDAY para obtener el indice del dia de la semana.

Escrito por Eduardo Lázaro