Solución:
La función de extracción parece útil y la función de fecha que encontré resuelve algunos de mis problemas, pero ¿hay alguna forma de replicar el date_trunc de PostgreSQL?
En efecto, EXTRACT
parece que va a ser la coincidencia más cercana para este caso específico.
Tu código original en PG:
WHERE date_trunc('month', QUERY_DATE) BETWEEN
date_trunc('month', now()) - INTERVAL '4 MONTH' AND
date_trunc('month', now() - INTERVAL '1 WEEK')
Utilizando EXTRACT
:
WHERE EXTRACT(YEAR_MONTH FROM QUERY_DATE)
BETWEEN
EXTRACT(YEAR_MONTH FROM NOW() - INTERVAL 4 MONTH)
AND
EXTRACT(YEAR_MONTH FROM NOW() - INTERVAL 1 WEEK)
Si bien debería ser funcionalmente idéntico, esto en realidad está transformando las fechas en una cadena AAAAMM antes de hacer la comparación.
Otra opción sería usar DATE_FORMAT
para reconstruir la cadena de fecha y forzarla al comienzo del mes:
WHERE DATE_FORMAT(QUERY_DATE, '%Y-%m-01')
BETWEEN
DATE_FORMAT(NOW() - INTERVAL 4 MONTH, '%Y-%m-01')
AND
DATE_FORMAT(NOW() - INTERVAL 1 WEEK, '%Y-%m-01')
Además, tenga en cuenta que MySQL es realmente deficiente para tratar con rangos de fechas, incluso cuando el campo está indexado. Probablemente terminará con un escaneo completo de la tabla si no tiene cuidado.
tarde a la fiesta, pero …
hay una forma de obtener una fecha truncada dado que conoce el intervalo. Por ejemplo, si el intervalo es MONTH
, podrías obtener la fecha de hoynow()
) truncado al mes usando lo siguiente:
select date_add('1900-01-01', interval TIMESTAMPDIFF(MONTH, '1900-01-01', now()) MONTH);
Dado lo anterior, se podría crear una función para cuidar también de los otros intervalos:
DELIMITER //
create function date_trunc(vInterval varchar(7), vDate timestamp)
returns timestamp
begin
declare toReturn timestamp;
if vInterval="year" then set toReturn = date_add('1900-01-01', interval TIMESTAMPDIFF(YEAR, '1900-01-01', vDate) YEAR);
elseif vInterval="quarter" then set toReturn = date_add('1900-01-01', interval TIMESTAMPDIFF(QUARTER, '1900-01-01', vDate) QUARTER);
elseif vInterval="month" then set toReturn = date_add('1900-01-01', interval TIMESTAMPDIFF(MONTH, '1900-01-01', vDate) MONTH);
elseif vInterval="week" then set toReturn = date_add('1900-01-01', interval TIMESTAMPDIFF(WEEK, '1900-01-01', vDate) WEEK);
elseif vInterval="day" then set toReturn = date_add('1900-01-01', interval TIMESTAMPDIFF(DAY, '1900-01-01', vDate) DAY);
elseif vInterval="hour" then set toReturn = date_add('1900-01-01', interval TIMESTAMPDIFF(HOUR, '1900-01-01', vDate) HOUR);
elseif vInterval="minute" then set toReturn = date_add('1900-01-01', interval TIMESTAMPDIFF(MINUTE, '1900-01-01', vDate) MINUTE);
END IF;
return toReturn;
end//
DELIMITER ;
Úselo así:
select date_trunc('quarter', now())