YEAR
La función YEAR extrae el componente de año de una fecha y lo devuelve como un número entero. Es la forma más directa y legible de obtener el año de un valor DATE, DATETIME o TIMESTAMP en MySQL. Aunque podrías usar EXTRACT(YEAR FROM fecha) para lograr lo mismo, YEAR() es más concisa y se ha convertido en la opción preferida en la mayoría de proyectos MySQL.
YEAR es una de las funciones de fecha que más usarás en la práctica. Filtrar registros por año, agrupar ventas anuales, comparar rendimiento entre años: todos estos escenarios aparecen constantemente en aplicaciones reales.
Sintaxis
YEAR(fecha)El argumento fecha puede ser un valor de tipo DATE, DATETIME, TIMESTAMP o una cadena con formato de fecha válido. La función devuelve un entero entre 1000 y 9999, que corresponde al rango de años que MySQL puede almacenar. Si el valor de entrada es '0000-00-00', la función devuelve 0.
Comportamiento básico
En su forma más simple, YEAR toma una fecha y devuelve el año como número:
SELECT
YEAR('2025-08-15') AS desde_date,
YEAR('2025-08-15 14:30:00') AS desde_datetime,
YEAR(NOW()) AS anio_actual;| desde_date | desde_datetime | anio_actual |
|---|---|---|
| 2025 | 2025 | 2025 |
No importa si le pasas un DATE o un DATETIME: YEAR ignora la parte de tiempo y devuelve únicamente el año. El resultado siempre es un entero, sin ceros a la izquierda ni formato especial.
Usar YEAR con columnas de tabla
El uso más habitual es aplicar YEAR sobre una columna de fecha en tus consultas:
SELECT
nombre,
fecha_contratacion,
YEAR(fecha_contratacion) AS anio_contratacion
FROM empleados
LIMIT 5;| nombre | fecha_contratacion | anio_contratacion |
|---|---|---|
| María García | 2019-03-15 | 2019 |
| Carlos López | 2020-07-22 | 2020 |
| Ana Rodríguez | 2021-01-10 | 2021 |
| Pedro Martínez | 2022-11-05 | 2022 |
| Laura Sánchez | 2023-06-18 | 2023 |
Caso práctico: filtrar registros por año
Una de las aplicaciones más comunes de YEAR es filtrar registros de un año específico en la cláusula WHERE. Esto es más legible que usar rangos de fechas:
SELECT
id_venta,
fecha_venta,
cliente,
total
FROM ventas
WHERE YEAR(fecha_venta) = 2024
ORDER BY fecha_venta
LIMIT 5;| id_venta | fecha_venta | cliente | total |
|---|---|---|---|
| 3201 | 2024-01-02 | Importaciones del Sur | 4500.00 |
| 3202 | 2024-01-03 | Distribuciones Norte | 2300.00 |
| 3203 | 2024-01-03 | Comercial Mediterráneo | 1875.50 |
| 3204 | 2024-01-04 | Logística Central | 6200.00 |
| 3205 | 2024-01-05 | Mayoristas Unidos | 3150.75 |
Sin embargo, hay un detalle de rendimiento importante: YEAR(fecha_venta) = 2024 no puede aprovechar un índice en la columna fecha_venta porque MySQL necesita aplicar la función a cada fila antes de comparar. Si tienes millones de registros, es más eficiente usar un rango:
-- Más eficiente con índices
SELECT id_venta, fecha_venta, cliente, total
FROM ventas
WHERE fecha_venta >= '2024-01-01'
AND fecha_venta < '2025-01-01';Ambas consultas devuelven los mismos resultados, pero la segunda puede usar un índice en fecha_venta. Usa YEAR() en WHERE cuando la tabla es pequeña o cuando la legibilidad es más importante que el rendimiento. Para tablas grandes, prefiere rangos.
Caso práctico: agrupar ventas por año
El escenario clásico de YEAR en combinación con GROUP BY: obtener un resumen anual de ventas.
SELECT
YEAR(fecha_venta) AS anio,
COUNT(*) AS num_ventas,
SUM(total) AS ingresos_totales,
ROUND(AVG(total), 2) AS ticket_medio,
MIN(total) AS venta_minima,
MAX(total) AS venta_maxima
FROM ventas
WHERE fecha_venta >= '2021-01-01'
GROUP BY YEAR(fecha_venta)
ORDER BY anio;| anio | num_ventas | ingresos_totales | ticket_medio | venta_minima | venta_maxima |
|---|---|---|---|---|---|
| 2021 | 3420 | 513000.00 | 150.00 | 12.50 | 8500.00 |
| 2022 | 3890 | 622400.00 | 160.04 | 15.00 | 9200.00 |
| 2023 | 4250 | 722500.00 | 170.00 | 18.75 | 11500.00 |
| 2024 | 4810 | 865800.00 | 180.00 | 22.00 | 12800.00 |
Este tipo de consulta es el pan de cada día en cualquier dashboard empresarial. De un vistazo puedes ver la evolución del negocio: más ventas cada año, ticket medio creciente y ventas máximas más altas.
Caso práctico: comparar año actual vs anterior
Un patrón muy útil es comparar las cifras del año en curso con las del año anterior para medir el crecimiento:
SELECT
YEAR(fecha_venta) AS anio,
SUM(total) AS ingresos,
LAG(SUM(total)) OVER (ORDER BY YEAR(fecha_venta)) AS ingresos_anterior,
ROUND(
(SUM(total) - LAG(SUM(total)) OVER (ORDER BY YEAR(fecha_venta)))
/ LAG(SUM(total)) OVER (ORDER BY YEAR(fecha_venta)) * 100,
1) AS crecimiento_pct
FROM ventas
WHERE YEAR(fecha_venta) >= 2021
GROUP BY YEAR(fecha_venta)
ORDER BY anio;| anio | ingresos | ingresos_anterior | crecimiento_pct |
|---|---|---|---|
| 2021 | 513000.00 | NULL | NULL |
| 2022 | 622400.00 | 513000.00 | 21.3 |
| 2023 | 722500.00 | 622400.00 | 16.1 |
| 2024 | 865800.00 | 722500.00 | 19.8 |
La función ventana LAG combinada con YEAR te permite calcular el porcentaje de crecimiento interanual directamente en SQL, sin necesidad de procesar los datos en tu aplicación.
Caso práctico: rangos de años con BETWEEN
A veces necesitas filtrar por un rango de años en lugar de un año exacto. YEAR combinado con BETWEEN lo hace natural:
SELECT
nombre,
fecha_contratacion,
YEAR(fecha_contratacion) AS anio
FROM empleados
WHERE YEAR(fecha_contratacion) BETWEEN 2020 AND 2023
ORDER BY fecha_contratacion;| nombre | fecha_contratacion | anio |
|---|---|---|
| Carlos López | 2020-07-22 | 2020 |
| Ana Rodríguez | 2021-01-10 | 2021 |
| Pedro Martínez | 2022-11-05 | 2022 |
| Laura Sánchez | 2023-06-18 | 2023 |
Esto selecciona todos los empleados contratados entre 2020 y 2023, ambos inclusive. La expresión es más legible que escribir rangos de fechas completos.
YEAR vs EXTRACT(YEAR FROM ...)
Funcionalmente, YEAR() y EXTRACT(YEAR FROM ...) son idénticas:
SELECT
YEAR('2025-08-15') AS con_year,
EXTRACT(YEAR FROM '2025-08-15') AS con_extract;| con_year | con_extract |
|---|---|
| 2025 | 2025 |
La diferencia es puramente estilística. YEAR() es más corta y más habitual en código MySQL. EXTRACT() es estándar SQL y se porta mejor a otros motores de bases de datos. Si tu proyecto solo usa MySQL, YEAR() es perfectamente válida. Si necesitas compatibilidad con PostgreSQL u Oracle, usa EXTRACT.
YEAR con NULL
Si la fecha de entrada es NULL, YEAR devuelve NULL sin generar error:
SELECT
YEAR(NULL) AS resultado,
YEAR('0000-00-00') AS fecha_cero;| resultado | fecha_cero |
|---|---|
| NULL | 0 |
Observa que YEAR('0000-00-00') devuelve 0, no NULL. Esto puede ser relevante si tu tabla tiene fechas con el valor por defecto '0000-00-00', que MySQL permite cuando NO_ZERO_DATE no está activo en el modo SQL.
Combinación con otras funciones
YEAR se combina frecuentemente con MONTH para crear agrupaciones año-mes, o con funciones de agregación para informes complejos:
SELECT
YEAR(fecha_venta) AS anio,
MONTH(fecha_venta) AS mes,
SUM(total) AS ingresos
FROM ventas
WHERE YEAR(fecha_venta) = 2024
GROUP BY YEAR(fecha_venta), MONTH(fecha_venta)
ORDER BY anio, mes;| anio | mes | ingresos |
|---|---|---|
| 2024 | 1 | 62400.00 |
| 2024 | 2 | 58900.00 |
| 2024 | 3 | 64700.00 |
| 2024 | 4 | 71200.00 |
| 2024 | 5 | 68500.00 |
| 2024 | 6 | 72300.00 |
Esta combinación YEAR + MONTH es tan habitual que MySQL ofrece la alternativa EXTRACT(YEAR_MONTH FROM fecha) como atajo. Ambos enfoques son válidos; elige el que resulte más claro para tu equipo.
En el siguiente artículo veremos MONTH para extraer el mes.
Escrito por Eduardo Lázaro
