QUARTER
La funcion QUARTER() devuelve un entero del 1 al 4 que indica el trimestre al que pertenece una fecha. El trimestre 1 abarca enero a marzo, el 2 de abril a junio, el 3 de julio a septiembre y el 4 de octubre a diciembre. Es una funcion esencial para el analisis financiero y comercial, ya que la mayoria de empresas estructuran sus reportes, objetivos y presupuestos en periodos trimestrales.
Sintaxis
QUARTER(fecha)El parametro fecha acepta un valor de tipo DATE o DATETIME. La funcion devuelve un entero entre 1 y 4:
| Trimestre | Meses |
|---|---|
| 1 | Enero, Febrero, Marzo |
| 2 | Abril, Mayo, Junio |
| 3 | Julio, Agosto, Septiembre |
| 4 | Octubre, Noviembre, Diciembre |
Si la fecha es NULL o no es valida, QUARTER() devuelve NULL.
Comportamiento basico
Para obtener el trimestre de una fecha:
SELECT QUARTER('2026-02-14') AS trimestre;| trimestre |
|---|
| 1 |
Febrero pertenece al primer trimestre. Puedes verificar las fronteras entre trimestres:
SELECT
QUARTER('2026-03-31') AS fin_q1,
QUARTER('2026-04-01') AS inicio_q2,
QUARTER('2026-06-30') AS fin_q2,
QUARTER('2026-07-01') AS inicio_q3,
QUARTER('2026-09-30') AS fin_q3,
QUARTER('2026-10-01') AS inicio_q4;| fin_q1 | inicio_q2 | fin_q2 | inicio_q3 | fin_q3 | inicio_q4 |
|---|---|---|---|---|---|
| 1 | 2 | 2 | 3 | 3 | 4 |
Aplicada sobre columnas de una tabla, QUARTER() te permite identificar rapidamente a que trimestre pertenece cada registro:
SELECT
nombre,
fecha_contratacion,
QUARTER(fecha_contratacion) AS trimestre_ingreso
FROM empleados
ORDER BY fecha_contratacion
LIMIT 5;| nombre | fecha_contratacion | trimestre_ingreso |
|---|---|---|
| Carlos Rodriguez | 2022-07-01 | 3 |
| Maria Garcia | 2023-03-15 | 1 |
| Pedro Sanchez | 2023-11-20 | 4 |
| Ana Martinez | 2024-01-08 | 1 |
| Laura Fernandez | 2024-06-03 | 2 |
Caso practico: reporte de ingresos trimestrales
El uso mas directo de QUARTER() es generar reportes trimestrales de ventas:
SELECT
CONCAT('Q', QUARTER(fecha_pedido)) AS trimestre,
COUNT(*) AS total_pedidos,
ROUND(SUM(total), 2) AS ingresos,
ROUND(AVG(total), 2) AS ticket_medio,
COUNT(DISTINCT cliente_id) AS clientes_activos
FROM pedidos
WHERE YEAR(fecha_pedido) = 2025
GROUP BY QUARTER(fecha_pedido)
ORDER BY QUARTER(fecha_pedido);| trimestre | total_pedidos | ingresos | ticket_medio | clientes_activos |
|---|---|---|---|---|
| Q1 | 476 | 117771.60 | 247.42 | 185 |
| Q2 | 555 | 141751.15 | 255.41 | 210 |
| Q3 | 585 | 152301.90 | 260.34 | 225 |
| Q4 | 650 | 181700.95 | 279.54 | 248 |
La etiqueta CONCAT('Q', QUARTER(...)) produce el formato Q1, Q2, Q3, Q4 que es universalmente reconocido en el mundo empresarial. El reporte muestra una tendencia creciente a lo largo del ano, con el cuarto trimestre como el periodo mas fuerte, algo habitual en el comercio minorista por las campanas de fin de ano.
Caso practico: comparar trimestres entre anos
Para analizar la evolucion interanual por trimestres, combina QUARTER() con YEAR():
SELECT
CONCAT('Q', QUARTER(fecha_pedido)) AS trimestre,
ROUND(SUM(CASE WHEN YEAR(fecha_pedido) = 2024 THEN total ELSE 0 END), 2) AS ingresos_2024,
ROUND(SUM(CASE WHEN YEAR(fecha_pedido) = 2025 THEN total ELSE 0 END), 2) AS ingresos_2025,
ROUND(
(SUM(CASE WHEN YEAR(fecha_pedido) = 2025 THEN total ELSE 0 END) -
SUM(CASE WHEN YEAR(fecha_pedido) = 2024 THEN total ELSE 0 END)) /
NULLIF(SUM(CASE WHEN YEAR(fecha_pedido) = 2024 THEN total ELSE 0 END), 0) * 100,
1) AS crecimiento_pct
FROM pedidos
WHERE YEAR(fecha_pedido) IN (2024, 2025)
GROUP BY QUARTER(fecha_pedido)
ORDER BY QUARTER(fecha_pedido);| trimestre | ingresos_2024 | ingresos_2025 | crecimiento_pct |
|---|---|---|---|
| Q1 | 99400.70 | 117771.60 | 18.5 |
| Q2 | 121900.10 | 141751.15 | 16.3 |
| Q3 | 130200.50 | 152301.90 | 17.0 |
| Q4 | 158500.80 | 181700.95 | 14.6 |
Este analisis revela que el crecimiento interanual se mantuvo entre el 14% y el 18% en todos los trimestres, con el primer trimestre mostrando el mayor crecimiento relativo. Este tipo de comparaciones son fundamentales para la toma de decisiones estrategicas, ya que permiten identificar si el crecimiento es uniforme o si hay trimestres que necesitan atencion especial.
Caso practico: rendimiento de productos por trimestre
Para detectar estacionalidad en las categorias de productos:
SELECT
c.nombre AS categoria,
CONCAT('Q', QUARTER(p.fecha_pedido)) AS trimestre,
COUNT(*) AS unidades,
ROUND(SUM(dp.cantidad * dp.precio_unitario), 2) AS ingresos
FROM pedidos p
JOIN detalle_pedidos dp ON p.id = dp.pedido_id
JOIN productos pr ON dp.producto_id = pr.id
JOIN categorias c ON pr.categoria_id = c.id
WHERE YEAR(p.fecha_pedido) = 2025
AND c.nombre IN ('Electrónica', 'Ropa', 'Deportes')
GROUP BY c.nombre, QUARTER(p.fecha_pedido)
ORDER BY c.nombre, QUARTER(p.fecha_pedido);| categoria | trimestre | unidades | ingresos |
|---|---|---|---|
| Deportes | Q1 | 135 | 18200.50 |
| Deportes | Q2 | 210 | 28500.30 |
| Deportes | Q3 | 185 | 24800.80 |
| Deportes | Q4 | 120 | 16100.40 |
| Electrónica | Q1 | 247 | 85300.20 |
| Electrónica | Q2 | 225 | 78100.50 |
| Electrónica | Q3 | 210 | 72400.30 |
| Electrónica | Q4 | 298 | 102500.80 |
| Ropa | Q1 | 320 | 28400.60 |
| Ropa | Q2 | 285 | 25200.30 |
| Ropa | Q3 | 250 | 22100.50 |
| Ropa | Q4 | 380 | 33800.40 |
Los datos revelan patrones claros: Deportes tiene su pico en Q2 (primavera-verano), mientras que Electronica y Ropa concentran sus mayores ventas en Q4 (campanas navidenas). Esta informacion es valiosa para planificar inventario y campanas de marketing.
Manejo de NULL
QUARTER() devuelve NULL cuando recibe un valor nulo o una fecha invalida:
SELECT
QUARTER(NULL) AS resultado_null,
QUARTER('2025-00-15') AS mes_invalido,
QUARTER('0000-00-00') AS fecha_cero;| resultado_null | mes_invalido | fecha_cero |
|---|---|---|
| NULL | NULL | NULL |
En consultas con columnas que pueden contener nulos, protege tus calculos:
SELECT
CONCAT('Q', QUARTER(fecha_pedido)) AS trimestre,
COUNT(*) AS pedidos
FROM pedidos
WHERE fecha_pedido IS NOT NULL
AND YEAR(fecha_pedido) = 2025
GROUP BY QUARTER(fecha_pedido)
ORDER BY QUARTER(fecha_pedido);Combinacion con otras funciones
QUARTER() se combina naturalmente con YEAR() para crear identificadores unicos de trimestre:
SELECT
CONCAT(YEAR(fecha_pedido), '-Q', QUARTER(fecha_pedido)) AS periodo,
COUNT(*) AS pedidos,
ROUND(SUM(total), 2) AS ingresos
FROM pedidos
WHERE fecha_pedido >= '2025-07-01'
GROUP BY YEAR(fecha_pedido), QUARTER(fecha_pedido)
ORDER BY YEAR(fecha_pedido), QUARTER(fecha_pedido);| periodo | pedidos | ingresos |
|---|---|---|
| 2025-Q3 | 585 | 152301.90 |
| 2025-Q4 | 650 | 181700.95 |
| 2026-Q1 | 327 | 82140.50 |
Tambien puedes calcular las fechas de inicio y fin de un trimestre para usarlas en filtros:
SELECT
QUARTER(CURDATE()) AS trimestre_actual,
MAKEDATE(YEAR(CURDATE()), 1) +
INTERVAL (QUARTER(CURDATE()) - 1) * 3 MONTH AS inicio_trimestre,
LAST_DAY(MAKEDATE(YEAR(CURDATE()), 1) +
INTERVAL QUARTER(CURDATE()) * 3 - 1 MONTH) AS fin_trimestre;| trimestre_actual | inicio_trimestre | fin_trimestre |
|---|---|---|
| 1 | 2026-01-01 | 2026-03-31 |
Otra combinacion util es usar QUARTER() dentro de funciones de ventana para calcular acumulados trimestrales:
SELECT
fecha_pedido,
total,
SUM(total) OVER (
PARTITION BY YEAR(fecha_pedido), QUARTER(fecha_pedido)
ORDER BY fecha_pedido
) AS acumulado_trimestral
FROM pedidos
WHERE fecha_pedido BETWEEN '2026-01-01' AND '2026-01-10'
ORDER BY fecha_pedido;| fecha_pedido | total | acumulado_trimestral |
|---|---|---|
| 2026-01-02 | 245.00 | 245.00 |
| 2026-01-03 | 189.50 | 434.50 |
| 2026-01-04 | 312.80 | 747.30 |
| 2026-01-05 | 156.40 | 903.70 |
| 2026-01-06 | 278.30 | 1182.00 |
| 2026-01-07 | 445.00 | 1627.00 |
| 2026-01-08 | 95.80 | 1722.80 |
| 2026-01-09 | 342.00 | 2064.80 |
| 2026-01-10 | 210.50 | 2275.30 |
La clausula PARTITION BY YEAR(fecha_pedido), QUARTER(fecha_pedido) reinicia el acumulado al comenzar cada trimestre, lo que te permite ver el progreso de ingresos dentro del trimestre actual.
En el siguiente articulo veremos LAST_DAY para obtener el ultimo dia del mes.
Escrito por Eduardo Lázaro
