Curso de SQL completo: SELECT, JOIN, agregaciones, índices y transacciones (2026)

Las fechas y horas son uno de los tipos de datos más habituales en bases de datos: pedidos, registros de usuarios, logs de acceso, tareas programadas... casi todo tiene una dimensión temporal. MySQL ofrece un conjunto amplio de funciones para obtener, formatear y calcular con fechas directamente en SQL.

En este capítulo cubrimos las funciones más usadas: obtener la fecha y hora actual, extraer partes de una fecha, calcular diferencias y formatear para mostrar al usuario.

Obtener la fecha y hora actuales

-- Fecha y hora actual (según el servidor)
SELECT NOW();           -- '2026-05-09 18:00:00'
SELECT CURRENT_TIMESTAMP; -- idéntico a NOW()

-- Solo fecha
SELECT CURDATE();       -- '2026-05-09'
SELECT CURRENT_DATE;    -- idéntico a CURDATE()

-- Solo hora
SELECT CURTIME();       -- '18:00:00'
SELECT CURRENT_TIME;    -- idéntico a CURTIME()

-- Marca de tiempo Unix (segundos desde 1970-01-01)
SELECT UNIX_TIMESTAMP();            -- número entero
SELECT FROM_UNIXTIME(1715270400);   -- convierte de Unix a DATETIME

Extraer partes de una fecha

-- Funciones individuales
SELECT YEAR('2026-05-09');    -- 2026
SELECT MONTH('2026-05-09');   -- 5
SELECT DAY('2026-05-09');     -- 9
SELECT HOUR('18:30:45');      -- 18
SELECT MINUTE('18:30:45');    -- 30
SELECT SECOND('18:30:45');    -- 45

-- EXTRACT: más estándar (funciona en MySQL y PostgreSQL)
SELECT EXTRACT(YEAR  FROM '2026-05-09');     -- 2026
SELECT EXTRACT(MONTH FROM fecha_alta) AS mes FROM clientes;

-- Día de la semana (1=Domingo, 7=Sábado en MySQL)
SELECT DAYOFWEEK('2026-05-09');    -- 7 (sábado)
-- WEEKDAY: 0=Lunes, 6=Domingo
SELECT WEEKDAY('2026-05-09');      -- 5 (sábado)

-- Número de semana del año
SELECT WEEK('2026-05-09');         -- 18
SELECT DAYOFYEAR('2026-05-09');    -- 129

Calcular diferencias entre fechas

-- DATEDIFF: diferencia en días (fecha1 - fecha2)
SELECT DATEDIFF('2026-05-09', '2024-01-01');    -- días transcurridos
SELECT DATEDIFF(CURDATE(), fecha_alta) AS dias_desde_alta FROM clientes;

-- TIMESTAMPDIFF: diferencia en la unidad que elijas
SELECT TIMESTAMPDIFF(YEAR,  '1990-06-15', CURDATE()) AS edad;
SELECT TIMESTAMPDIFF(MONTH, '2024-01-01', CURDATE()) AS meses;
SELECT TIMESTAMPDIFF(DAY,   '2024-01-01', CURDATE()) AS dias;

-- Ejemplo: clientes que llevan más de un año registrados
SELECT nombre, fecha_alta
FROM clientes
WHERE TIMESTAMPDIFF(YEAR, fecha_alta, CURDATE()) >= 1;

Sumar y restar intervalos

-- DATE_ADD / DATE_SUB
SELECT DATE_ADD(CURDATE(), INTERVAL 30 DAY);    -- dentro de 30 días
SELECT DATE_ADD(CURDATE(), INTERVAL 3 MONTH);   -- dentro de 3 meses
SELECT DATE_ADD(CURDATE(), INTERVAL 1 YEAR);    -- dentro de un año
SELECT DATE_SUB('2026-05-09', INTERVAL 7 DAY);  -- hace 7 días

-- Con horas y minutos
SELECT DATE_ADD(NOW(), INTERVAL '1:30' HOUR_MINUTE);

-- Operador + INTERVAL (equivalente, más legible)
SELECT '2026-01-01' + INTERVAL 100 DAY;   -- 2026-04-11

-- Ejemplo: pedidos de las últimas 48 horas
SELECT id, fecha, total FROM pedidos
WHERE fecha >= NOW() - INTERVAL 48 HOUR;

Formatear fechas para mostrar al usuario

-- DATE_FORMAT: equivalente a strftime() de C / date() de PHP
SELECT DATE_FORMAT(fecha_alta, '%d/%m/%Y')        AS fecha_es  FROM clientes;
-- '15/01/2023'

SELECT DATE_FORMAT(fecha_alta, '%d de %M de %Y')  AS fecha_larga FROM clientes;
-- '15 de January de 2023' (nombres de meses en inglés en MySQL)

-- Para nombres en español, mapear el número de mes con CASE o ELT():
SELECT
    nombre,
    CONCAT(
        DAY(fecha_alta), ' de ',
        ELT(MONTH(fecha_alta),
            'enero','febrero','marzo','abril','mayo','junio',
            'julio','agosto','septiembre','octubre','noviembre','diciembre'),
        ' de ', YEAR(fecha_alta)
    ) AS fecha_castellano
FROM clientes;

Comparar fechas en WHERE

-- Pedidos de hoy
SELECT * FROM pedidos WHERE DATE(fecha) = CURDATE();

-- Pedidos del mes actual
SELECT * FROM pedidos
WHERE YEAR(fecha) = YEAR(CURDATE())
  AND MONTH(fecha) = MONTH(CURDATE());

-- Nota: aplicar funciones sobre la columna indexada (como YEAR(fecha))
-- impide usar el índice. Mejor comprar con un rango:
SELECT * FROM pedidos
WHERE fecha >= DATE_FORMAT(CURDATE(), '%Y-%m-01')
  AND fecha <  DATE_FORMAT(CURDATE(), '%Y-%m-01') + INTERVAL 1 MONTH;

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP