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:
| Modo | Primer dia | Rango | Primera semana es... |
|---|---|---|---|
| 0 | Domingo | 0-53 | La que tiene un domingo en este ano |
| 1 | Lunes | 0-53 | La que tiene 4 o mas dias en este ano |
| 2 | Domingo | 1-53 | La que tiene un domingo en este ano |
| 3 | Lunes | 1-53 | La que tiene 4 o mas dias en este ano (ISO) |
| 4 | Domingo | 0-53 | La que tiene 4 o mas dias en este ano |
| 5 | Lunes | 0-53 | La que tiene un lunes en este ano |
| 6 | Domingo | 1-53 | La que tiene 4 o mas dias en este ano |
| 7 | Lunes | 1-53 | La 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_enero | semana_4_enero | semana_14_feb |
|---|---|---|
| 0 | 1 | 6 |
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_0 | modo_1 | modo_2 | modo_3 |
|---|---|---|---|
| 0 | 1 | 52 | 1 |
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;| semana | desde | hasta | total_pedidos | ingresos |
|---|---|---|---|---|
| 1 | 2026-01-01 | 2026-01-04 | 28 | 6850.30 |
| 2 | 2026-01-05 | 2026-01-11 | 52 | 13200.50 |
| 3 | 2026-01-12 | 2026-01-18 | 48 | 12100.80 |
| 4 | 2026-01-19 | 2026-01-25 | 55 | 14350.20 |
| 5 | 2026-01-26 | 2026-02-01 | 51 | 12800.40 |
| 6 | 2026-02-02 | 2026-02-08 | 47 | 11650.30 |
| 7 | 2026-02-09 | 2026-02-14 | 46 | 11189.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;| fecha | semana_iso | dia_semana |
|---|---|---|
| 2025-12-29 | 1 | 0 |
| 2025-12-30 | 1 | 1 |
| 2025-12-31 | 1 | 2 |
| 2026-01-01 | 1 | 3 |
| 2026-01-02 | 1 | 4 |
| 2026-01-03 | 1 | 5 |
| 2026-01-04 | 1 | 6 |
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;| ano | semana | pedidos | ingresos |
|---|---|---|---|
| 2025 | 7 | 42 | 10350.80 |
| 2026 | 7 | 46 | 11189.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_null | fecha_invalida | fecha_cero |
|---|---|---|
| NULL | NULL | NULL |
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;| ano | semana | pedidos | ingresos |
|---|---|---|---|
| 2025 | 49 | 48 | 12400.30 |
| 2025 | 50 | 52 | 14200.50 |
| 2025 | 51 | 56 | 15800.80 |
| 2025 | 52 | 58 | 16200.40 |
| 2026 | 1 | 28 | 6850.30 |
| 2026 | 2 | 52 | 13200.50 |
| 2026 | 3 | 48 | 12100.80 |
| 2026 | 4 | 55 | 14350.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);| etiqueta | pedidos |
|---|---|
| S01-2026 | 28 |
| S02-2026 | 52 |
| S03-2026 | 48 |
| S04-2026 | 55 |
En el siguiente articulo veremos WEEKDAY para obtener el indice del dia de la semana.
Escrito por Eduardo Lázaro
