Quase toda consulta analitica comeca com "nos ultimos N dias" ou "no mes atual". Para que esses filtros sejam corretos e rapidos, voce precisa saber a diferenca entre NOW() e CURRENT_DATE, e como somar intervalos a datas.
NOW() e CURRENT_DATE: o que retornam
O PostgreSQL oferece duas formas basicas de pedir o "agora":
NOW() (alias CURRENT_TIMESTAMP) retorna um timestamptz — um momento com data e hora.
CURRENT_DATE retorna um date — apenas o dia de hoje, sem hora.
SELECT
NOW() AS ts,
CURRENT_DATE AS today,
CURRENT_TIME AS clock;
A distincao importa ao comparar. created_at >= CURRENT_DATE mantem tudo a partir da meia-noite de hoje, enquanto created_at >= NOW() deixa so o futuro — quase nunca o que voce quer.
A janela dos "ultimos 7 dias"
O padrao canonico subtrai um intervalo do momento atual:
SELECT id, email, created_at
FROM users
WHERE created_at >= NOW() - INTERVAL '7 days'
ORDER BY created_at DESC;
INTERVAL '7 days' e um literal de duracao. Voce pode soma-lo ou subtrai-lo de qualquer timestamp ou date. Aceita hours, days, months, years e combinacoes como INTERVAL '1 day 6 hours'.
O mesmo truque escala para agregacoes — receita do ultimo dia, separada por status:
SELECT status, COUNT(*) AS cnt, SUM(amount) AS revenue
FROM orders
WHERE created_at >= NOW() - INTERVAL '24 hours'
GROUP BY status;
Detalhe util: o lado direito e constante por consulta, entao o planejador o avalia uma vez e ainda pode usar um indice em created_at.
"Este mes" e truncar ate o limite
Para janelas de calendario, date_trunc recorta um timestamp ate o inicio de um periodo:
SELECT id, amount
FROM orders
WHERE created_at >= date_trunc('month', CURRENT_DATE)
AND created_at < date_trunc('month', CURRENT_DATE) + INTERVAL '1 month';
Isso e mais solido que EXTRACT(MONTH FROM created_at) = 6: o limite superior se ajusta sozinho ao tamanho do mes, e a consulta continua sargable (usa indice). A mesma forma vale para 'day', 'week' e 'year'.
NOW() versus clock_timestamp()
A sutileza central: NOW() e fixado no inicio da transacao e nao muda ate ela terminar. Toda chamada dentro de uma mesma transacao retorna o mesmo valor.
BEGIN;
SELECT NOW();
SELECT NOW();
SELECT clock_timestamp();
COMMIT;
NOW() / CURRENT_TIMESTAMP / transaction_timestamp() — hora de inicio da transacao.
statement_timestamp() — inicio da instrucao atual.
clock_timestamp() — relogio real, muda a cada chamada.
Para logica de negocio e filtros, use NOW(): o valor e estavel e reproduzivel. clock_timestamp() serve apenas para medir tempo decorrido dentro de uma unica transacao.
Gotcha: nao envolva a coluna em uma funcao so para compara-la. WHERE date_trunc('day', created_at) = CURRENT_DATE desativa o indice em created_at. Compare a coluna crua contra os limites: created_at >= CURRENT_DATE AND created_at < CURRENT_DATE + INTERVAL '1 day'.
Diferencas de MySQL e ClickHouse
O MySQL escreve intervalos de outro jeito — sem aspas e com unidades no singular:
SELECT id, email
FROM users
WHERE created_at >= NOW() - INTERVAL 7 DAY;
SELECT CURDATE() AS today, NOW() AS ts;
- No MySQL,
CURDATE() e o analogo de CURRENT_DATE, e a unidade se escreve INTERVAL 7 DAY (DAY, HOUR, MONTH, sem s).
- O
NOW() do MySQL tambem e estavel dentro de uma instrucao; o relogio ao vivo vem de SYSDATE().
- O ClickHouse usa
now() com ajudantes como subtractDays(now(), 7) ou now() - INTERVAL 7 DAY; o inicio do mes e toStartOfMonth(now()).
Lembre de tres coisas: NOW() e o timestamp do tempo da transacao, CURRENT_DATE e so data, e a aritmetica de intervalos sobre uma coluna crua entrega janelas de tempo corretas e rapidas.
Quase toda consulta analitica comeca com "nos ultimos N dias" ou "no mes atual". Para que esses filtros sejam corretos e rapidos, voce precisa saber a diferenca entre
NOW()eCURRENT_DATE, e como somar intervalos a datas.NOW() e CURRENT_DATE: o que retornam
O PostgreSQL oferece duas formas basicas de pedir o "agora":
NOW()(aliasCURRENT_TIMESTAMP) retorna umtimestamptz— um momento com data e hora.CURRENT_DATEretorna umdate— apenas o dia de hoje, sem hora.SELECT NOW() AS ts, -- 2026-06-17 14:30:00+00 CURRENT_DATE AS today, -- 2026-06-17 CURRENT_TIME AS clock; -- 14:30:00+00A distincao importa ao comparar.
created_at >= CURRENT_DATEmantem tudo a partir da meia-noite de hoje, enquantocreated_at >= NOW()deixa so o futuro — quase nunca o que voce quer.A janela dos "ultimos 7 dias"
O padrao canonico subtrai um intervalo do momento atual:
SELECT id, email, created_at FROM users WHERE created_at >= NOW() - INTERVAL '7 days' ORDER BY created_at DESC;INTERVAL '7 days'e um literal de duracao. Voce pode soma-lo ou subtrai-lo de qualquertimestampoudate. Aceitahours,days,months,yearse combinacoes comoINTERVAL '1 day 6 hours'.O mesmo truque escala para agregacoes — receita do ultimo dia, separada por status:
SELECT status, COUNT(*) AS cnt, SUM(amount) AS revenue FROM orders WHERE created_at >= NOW() - INTERVAL '24 hours' GROUP BY status;Detalhe util: o lado direito e constante por consulta, entao o planejador o avalia uma vez e ainda pode usar um indice em
created_at."Este mes" e truncar ate o limite
Para janelas de calendario,
date_truncrecorta um timestamp ate o inicio de um periodo:SELECT id, amount FROM orders WHERE created_at >= date_trunc('month', CURRENT_DATE) AND created_at < date_trunc('month', CURRENT_DATE) + INTERVAL '1 month';Isso e mais solido que
EXTRACT(MONTH FROM created_at) = 6: o limite superior se ajusta sozinho ao tamanho do mes, e a consulta continua sargable (usa indice). A mesma forma vale para'day','week'e'year'.NOW() versus clock_timestamp()
A sutileza central:
NOW()e fixado no inicio da transacao e nao muda ate ela terminar. Toda chamada dentro de uma mesma transacao retorna o mesmo valor.BEGIN; SELECT NOW(); -- 14:30:00 -- ... trabalho demorado ... SELECT NOW(); -- ainda 14:30:00 SELECT clock_timestamp(); -- hora real do relogio, ja avancou COMMIT;NOW()/CURRENT_TIMESTAMP/transaction_timestamp()— hora de inicio da transacao.statement_timestamp()— inicio da instrucao atual.clock_timestamp()— relogio real, muda a cada chamada.Para logica de negocio e filtros, use
NOW(): o valor e estavel e reproduzivel.clock_timestamp()serve apenas para medir tempo decorrido dentro de uma unica transacao.Diferencas de MySQL e ClickHouse
O MySQL escreve intervalos de outro jeito — sem aspas e com unidades no singular:
-- MySQL SELECT id, email FROM users WHERE created_at >= NOW() - INTERVAL 7 DAY; SELECT CURDATE() AS today, NOW() AS ts;CURDATE()e o analogo deCURRENT_DATE, e a unidade se escreveINTERVAL 7 DAY(DAY,HOUR,MONTH, sems).NOW()do MySQL tambem e estavel dentro de uma instrucao; o relogio ao vivo vem deSYSDATE().now()com ajudantes comosubtractDays(now(), 7)ounow() - INTERVAL 7 DAY; o inicio do mes etoStartOfMonth(now()).Lembre de tres coisas:
NOW()e o timestamp do tempo da transacao,CURRENT_DATEe so data, e a aritmetica de intervalos sobre uma coluna crua entrega janelas de tempo corretas e rapidas.