WEEKDAY

La funcion WEEKDAY() devuelve un indice numerico que representa el dia de la semana de una fecha, usando una escala donde 0 es lunes y 6 es domingo. Esta convencion se alinea con el estandar ISO y con la forma en que la mayoria de paises europeos y latinoamericanos organizan la semana, lo que la hace particularmente practica cuando trabajas en entornos donde el lunes es el primer dia laborable.

Sintaxis

WEEKDAY(fecha)

El parametro fecha acepta valores de tipo DATE o DATETIME. La funcion devuelve un entero entre 0 y 6 segun esta correspondencia:

ValorDia
0Lunes
1Martes
2Miercoles
3Jueves
4Viernes
5Sabado
6Domingo

La principal diferencia con DAYOFWEEK() es la escala. DAYOFWEEK() sigue el estandar ODBC (1 = domingo, 7 = sabado), mientras que WEEKDAY() sigue la convencion ISO (0 = lunes, 6 = domingo). Es una distincion sutil pero critica que puede producir errores dificiles de detectar si confundes ambas funciones.

Comportamiento basico

Para obtener el indice del dia de la semana:

SELECT WEEKDAY('2026-02-14') AS dia_indice;
dia_indice
5

El 14 de febrero de 2026 es sabado, que corresponde al indice 5. Puedes verificar toda una semana para entender la correspondencia:

SELECT
    fecha,
    WEEKDAY(fecha) AS weekday_idx,
    DAYNAME(fecha) AS nombre_dia
FROM (
    SELECT '2026-02-09' AS fecha
    UNION SELECT '2026-02-10'
    UNION SELECT '2026-02-11'
    UNION SELECT '2026-02-12'
    UNION SELECT '2026-02-13'
    UNION SELECT '2026-02-14'
    UNION SELECT '2026-02-15'
) dias
ORDER BY fecha;
fechaweekday_idxnombre_dia
2026-02-090Monday
2026-02-101Tuesday
2026-02-112Wednesday
2026-02-123Thursday
2026-02-134Friday
2026-02-145Saturday
2026-02-156Sunday

La secuencia va de 0 (lunes) a 6 (domingo), lo que resulta natural para contextos laborales donde la semana empieza el lunes.

Caso practico: filtrar dias laborables

WEEKDAY() facilita el filtrado de dias laborables porque los valores del 0 al 4 corresponden exactamente a lunes-viernes:

SELECT
    fecha_pedido,
    total,
    WEEKDAY(fecha_pedido) AS dia_idx
FROM pedidos
WHERE WEEKDAY(fecha_pedido) <= 4
    AND fecha_pedido BETWEEN '2026-02-09' AND '2026-02-15'
ORDER BY fecha_pedido;
fecha_pedidototaldia_idx
2026-02-09445.000
2026-02-10156.401
2026-02-11278.302
2026-02-1295.803
2026-02-13342.004

La condicion WEEKDAY(fecha_pedido) <= 4 es mas limpia y legible que el equivalente con DAYOFWEEK(), que requeriria DAYOFWEEK(fecha_pedido) BETWEEN 2 AND 6. Del mismo modo, para seleccionar solo fines de semana basta con WEEKDAY(fecha_pedido) >= 5.

Puedes calcular cuantos dias laborables hay en un periodo:

SELECT
    COUNT(DISTINCT DATE(fecha_pedido)) AS dias_con_ventas,
    SUM(CASE WHEN WEEKDAY(fecha_pedido) <= 4 THEN 1 ELSE 0 END) AS pedidos_laborables,
    SUM(CASE WHEN WEEKDAY(fecha_pedido) >= 5 THEN 1 ELSE 0 END) AS pedidos_fin_semana
FROM pedidos
WHERE fecha_pedido BETWEEN '2026-01-01' AND '2026-01-31';
dias_con_ventaspedidos_laborablespedidos_fin_semana
3014538

Caso practico: rendimiento por dia de la semana en orden natural

Cuando generas un reporte de ventas agrupado por dia, WEEKDAY() te permite ordenar de lunes a domingo de forma directa:

SET lc_time_names = 'es_ES';
 
SELECT
    WEEKDAY(fecha_pedido) AS idx,
    DAYNAME(fecha_pedido) AS dia,
    COUNT(*) AS pedidos,
    ROUND(SUM(total), 2) AS ingresos,
    ROUND(AVG(total), 2) AS ticket_medio
FROM pedidos
WHERE YEAR(fecha_pedido) = 2025
GROUP BY WEEKDAY(fecha_pedido), DAYNAME(fecha_pedido)
ORDER BY WEEKDAY(fecha_pedido);
idxdiapedidosingresosticket_medio
0lunes18745320.50242.36
1martes16238750.80239.20
2miercoles17441200.30236.78
3jueves19548900.00250.77
4viernes23162450.75270.35
5sabado14535100.20242.07
6domingo9822800.40232.66

Con ORDER BY WEEKDAY(fecha_pedido), los resultados aparecen en el orden natural de lunes a domingo sin necesidad de trucos adicionales. Esto es mas limpio que usar DAYOFWEEK() donde tendrias que ajustar el orden con una expresion aritmetica para que lunes aparezca primero.

Caso practico: calcular el lunes de la semana actual

Un patron comun es encontrar el primer dia (lunes) de la semana de una fecha dada. Con WEEKDAY() esto es directo:

SELECT
    CURDATE() AS hoy,
    WEEKDAY(CURDATE()) AS dia_idx,
    DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY) AS lunes_de_esta_semana;
hoydia_idxlunes_de_esta_semana
2026-02-1452026-02-09

La formula DATE_SUB(fecha, INTERVAL WEEKDAY(fecha) DAY) resta tantos dias como indica el indice de WEEKDAY(), lo que siempre te lleva al lunes de esa semana. Puedes aplicar esto para agrupar ventas por semana empezando en lunes:

SELECT
    DATE_SUB(fecha_pedido, INTERVAL WEEKDAY(fecha_pedido) DAY) AS semana_inicio,
    COUNT(*) AS pedidos,
    ROUND(SUM(total), 2) AS ingresos
FROM pedidos
WHERE fecha_pedido BETWEEN '2026-01-01' AND '2026-01-31'
GROUP BY DATE_SUB(fecha_pedido, INTERVAL WEEKDAY(fecha_pedido) DAY)
ORDER BY semana_inicio;
semana_iniciopedidosingresos
2025-12-29122950.30
2026-01-055213200.50
2026-01-124812100.80
2026-01-195514350.20
2026-01-264410800.40

Manejo de NULL

WEEKDAY() devuelve NULL si la fecha es nula o invalida:

SELECT
    WEEKDAY(NULL) AS resultado_null,
    WEEKDAY('2025-04-31') AS abril_invalido;
resultado_nullabril_invalido
NULLNULL

El 31 de abril no existe (abril tiene 30 dias), asi que MySQL no puede determinar el dia de la semana y devuelve NULL. En consultas sobre tablas con fechas opcionales, puedes protegerte con COALESCE:

SELECT
    nombre,
    COALESCE(WEEKDAY(fecha_baja), -1) AS dia_baja
FROM empleados;

Combinacion con otras funciones

La relacion entre WEEKDAY() y DAYOFWEEK() se puede expresar con una formula. Ambas devuelven el dia de la semana pero con escalas diferentes:

SELECT
    CURDATE() AS fecha,
    WEEKDAY(CURDATE()) AS weekday_val,
    DAYOFWEEK(CURDATE()) AS dayofweek_val,
    MOD(WEEKDAY(CURDATE()) + 1, 7) + 1 AS weekday_to_dayofweek;
fechaweekday_valdayofweek_valweekday_to_dayofweek
2026-02-14577

Puedes combinar WEEKDAY() con ELT() para crear tu propia version localizada de nombres de dias sin depender de lc_time_names:

SELECT
    fecha_pedido,
    ELT(WEEKDAY(fecha_pedido) + 1,
        'Lunes', 'Martes', 'Miércoles', 'Jueves',
        'Viernes', 'Sábado', 'Domingo') AS dia_espanol,
    total
FROM pedidos
ORDER BY fecha_pedido DESC
LIMIT 5;
fecha_pedidodia_espanoltotal
2026-02-14Sabado189.50
2026-02-13Viernes342.00
2026-02-12Jueves95.80
2026-02-11Miercoles278.30
2026-02-10Martes156.40

La funcion ELT() devuelve el elemento en la posicion indicada por el primer argumento. Como WEEKDAY() devuelve 0 para lunes, sumamos 1 para que coincida con la posicion en ELT() (que empieza en 1). Esta tecnica te da control total sobre los nombres sin depender de la configuracion del locale del servidor.

En el siguiente articulo veremos YEARWEEK para obtener ano y semana combinados.

Escrito por Eduardo Lázaro