make_date y make_time construyen un valor a partir de numeros ya listos: pasas el ano, el mes y el dia (o la hora, el minuto y el segundo) como enteros separados, sin analizar una cadena. Son la herramienta ideal cuando las partes de una fecha ya estan en columnas distintas de un informe.
Sintaxis basica
make_date(year, month, day) devuelve un date, y make_time(hour, min, sec) devuelve un time. Los argumentos son enteros (los segundos son double precision para guardar una fraccion). No hay cadenas de formato como 'YYYY-MM-DD' ni las sorpresas de configuracion regional que las acompanan.
SELECT
make_date(2024, 3, 15) AS d,
make_time(14, 30, 0) AS t;
Los segundos aceptan una fraccion, asi que un momento con precision de milisegundos se construye sin convertir cadenas:
SELECT make_time(9, 5, 30.5) AS t;
Una marca de tiempo completa la da make_timestamp(year, month, day, hour, min, sec), y la version con zona es make_timestamptz(...).
Construir una fecha desde columnas separadas
El escenario principal es una tabla donde el ano, el mes y el dia se guardan como numeros en campos distintos. Supongamos que una carga desde un origen heredado dejo las partes de la fecha por separado:
SELECT
order_id,
make_date(y, m, d) AS order_date
FROM order_parts;
make_date elimina el dolor de la concatenacion y el CAST: no tienes que construir la cadena y || '-' || m || '-' || d y confiar en que un mes de un solo digito no rompa el formato. Los numeros entran en la funcion tal cual.
El mismo truco es util para filtrar por una fecha construida desde parametros. Todos los pedidos de un dia concreto, armados desde tres numeros:
SELECT id, user_id, amount
FROM orders
WHERE created_at::date = make_date(2024, 3, 15)
AND status = 'paid';
Validacion de partes fuera de rango
make_date no se queda callado ante un sinsentido: un valor fuera del rango valido lanza un error en lugar de pasar al mes siguiente como hace la aritmetica de intervalos.
SELECT make_date(2024, 13, 1);
SELECT make_date(2024, 2, 30);
Eso es a la vez una ventaja y una trampa:
- Ventaja: los datos sucios (mes
13, dia 0) se detectan al instante en vez de convertirse en silencio en una fecha incorrecta.
- Trampa: una sola fila rota en un recorrido grande tumba toda la consulta. Si los datos no estan limpios, valida las partes de antemano.
Protegete de las filas malas con un filtro previo:
SELECT order_id, make_date(y, m, d) AS order_date
FROM order_parts
WHERE m BETWEEN 1 AND 12
AND d BETWEEN 1 AND 31;
Un ano negativo se lee como antes de Cristo, asi que make_date(-1, 1, 1) no es un error sino 0001-01-01 BC. El ano cero se rechaza.
Cuando conviene make_time
make_time brilla cuando la hora y el minuto vienen de una configuracion o de un join. Por ejemplo, normalizar la "ventana de trabajo" de un departamento a una unica hora de inicio:
SELECT
e.dept,
COUNT(*) AS people,
make_time(9, 0, 0) AS shift_start
FROM employees e
GROUP BY e.dept;
El time ya armado se puede sumar a una fecha para obtener un momento completo sin analizar cadenas:
SELECT
u.id,
make_date(2024, 3, 15) + make_time(18, 0, 0) AS reminder_at
FROM users u
WHERE u.country = 'DE';
Diferencias en MySQL y ClickHouse
Los nombres y el comportamiento difieren de PostgreSQL.
- MySQL no tiene
make_date en el sentido habitual. Tiene MAKEDATE(year, dayofyear), que espera un ano y un dia del ano, no un mes y un dia. Para construir desde mes y dia se usa STR_TO_DATE, y para la hora se usa MAKETIME(hour, minute, second).
SELECT
STR_TO_DATE('2024-3-15', '%Y-%c-%e') AS d,
MAKETIME(14, 30, 0) AS t;
- ClickHouse ofrece
makeDate(year, month, day) y makeDateTime(year, month, day, hour, minute, second), cuyos nombres coinciden en sentido con PostgreSQL.
SELECT
makeDate(2024, 3, 15) AS d,
makeDateTime(2024, 3, 15, 14, 30, 0) AS t;
La diferencia clave al portar: MySQL MAKEDATE toma un dia del ano, no un mes y un dia, y tragara sin quejarse una entrada que PostgreSQL rechazaria. Revisa siempre la firma antes de mover una consulta entre bases de datos.
make_dateymake_timeconstruyen un valor a partir de numeros ya listos: pasas el ano, el mes y el dia (o la hora, el minuto y el segundo) como enteros separados, sin analizar una cadena. Son la herramienta ideal cuando las partes de una fecha ya estan en columnas distintas de un informe.Sintaxis basica
make_date(year, month, day)devuelve undate, ymake_time(hour, min, sec)devuelve untime. Los argumentos son enteros (los segundos sondouble precisionpara guardar una fraccion). No hay cadenas de formato como'YYYY-MM-DD'ni las sorpresas de configuracion regional que las acompanan.SELECT make_date(2024, 3, 15) AS d, -- 2024-03-15 make_time(14, 30, 0) AS t; -- 14:30:00Los segundos aceptan una fraccion, asi que un momento con precision de milisegundos se construye sin convertir cadenas:
SELECT make_time(9, 5, 30.5) AS t; -- 09:05:30.5Una marca de tiempo completa la da
make_timestamp(year, month, day, hour, min, sec), y la version con zona esmake_timestamptz(...).Construir una fecha desde columnas separadas
El escenario principal es una tabla donde el ano, el mes y el dia se guardan como numeros en campos distintos. Supongamos que una carga desde un origen heredado dejo las partes de la fecha por separado:
-- order_parts(order_id, y, m, d) SELECT order_id, make_date(y, m, d) AS order_date FROM order_parts;make_dateelimina el dolor de la concatenacion y elCAST: no tienes que construir la cadenay || '-' || m || '-' || dy confiar en que un mes de un solo digito no rompa el formato. Los numeros entran en la funcion tal cual.El mismo truco es util para filtrar por una fecha construida desde parametros. Todos los pedidos de un dia concreto, armados desde tres numeros:
SELECT id, user_id, amount FROM orders WHERE created_at::date = make_date(2024, 3, 15) AND status = 'paid';Validacion de partes fuera de rango
make_dateno se queda callado ante un sinsentido: un valor fuera del rango valido lanza un error en lugar de pasar al mes siguiente como hace la aritmetica de intervalos.SELECT make_date(2024, 13, 1); -- ERROR: date field value out of range SELECT make_date(2024, 2, 30); -- ERROR: date field value out of rangeEso es a la vez una ventaja y una trampa:
13, dia0) se detectan al instante en vez de convertirse en silencio en una fecha incorrecta.Protegete de las filas malas con un filtro previo:
SELECT order_id, make_date(y, m, d) AS order_date FROM order_parts WHERE m BETWEEN 1 AND 12 AND d BETWEEN 1 AND 31;Un ano negativo se lee como antes de Cristo, asi que
make_date(-1, 1, 1)no es un error sino0001-01-01 BC. El ano cero se rechaza.Cuando conviene make_time
make_timebrilla cuando la hora y el minuto vienen de una configuracion o de un join. Por ejemplo, normalizar la "ventana de trabajo" de un departamento a una unica hora de inicio:SELECT e.dept, COUNT(*) AS people, make_time(9, 0, 0) AS shift_start FROM employees e GROUP BY e.dept;El
timeya armado se puede sumar a una fecha para obtener un momento completo sin analizar cadenas:SELECT u.id, make_date(2024, 3, 15) + make_time(18, 0, 0) AS reminder_at FROM users u WHERE u.country = 'DE';Diferencias en MySQL y ClickHouse
Los nombres y el comportamiento difieren de PostgreSQL.
make_dateen el sentido habitual. TieneMAKEDATE(year, dayofyear), que espera un ano y un dia del ano, no un mes y un dia. Para construir desde mes y dia se usaSTR_TO_DATE, y para la hora se usaMAKETIME(hour, minute, second).SELECT STR_TO_DATE('2024-3-15', '%Y-%c-%e') AS d, -- 2024-03-15 MAKETIME(14, 30, 0) AS t; -- 14:30:00makeDate(year, month, day)ymakeDateTime(year, month, day, hour, minute, second), cuyos nombres coinciden en sentido con PostgreSQL.SELECT makeDate(2024, 3, 15) AS d, makeDateTime(2024, 3, 15, 14, 30, 0) AS t;La diferencia clave al portar: MySQL
MAKEDATEtoma un dia del ano, no un mes y un dia, y tragara sin quejarse una entrada que PostgreSQL rechazaria. Revisa siempre la firma antes de mover una consulta entre bases de datos.