0Pricing
SQL Interview Prep · Aula

Truncando e agrupando datas

Agrupando por semana, mês e trimestre com DATE_TRUNC e equivalentes.

Truncando e agrupando datas é uma aula grátis de SQL Interview Prep no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de SQL Interview Prep, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de SQL Interview Prep inclui 4 aulas no total.

Por que perguntam sobre agrupamento de datas

“Mostrar a receita por semana” ou “usuários ativos por mês” é o básico em entrevistas para analistas. A habilidade avaliada é reduzir carimbos de data e hora precisos a um intervalo mais amplo, para que as linhas sejam agrupadas.

O erro cometido por profissionais iniciantes é extrair apenas o número do mês, mesclando o mesmo mês de anos diferentes. A resposta profissional é o truncamento: mapear cada carimbo de data e hora para o início do seu período.

  • Agrupamentos por semana, mês, trimestre e ano
  • DATE_TRUNC e equivalentes de cada dialeto
  • Agrupamento correto para que os gráficos fiquem alinhados

DATE_TRUNC: a ferramenta principal

No PostgreSQL, DATE_TRUNC(unit, ts) zera tudo que é mais específico que a unidade informada. Truncar para 'month' transforma qualquer carimbo de data e hora de março em 2024-03-01 00:00:00.

O valor retornado ainda é um carimbo de data e hora, portanto é ordenado cronologicamente e agrupado perfeitamente. Essa é a função de data mais útil para relatórios.

SELECT DATE_TRUNC('month', TIMESTAMP '2024-03-17 14:30:00');
-- 2024-03-01 00:00:00

Agrupando a receita por mês

Este é o exemplo prático clássico. Trunque o carimbo de data e hora para o mês, depois agrupe e some. Como o intervalo inclui o ano, janeiro de 2023 e janeiro de 2024 permanecem separados.

Ordenar pelo valor truncado produz uma série temporal organizada, pronta para um gráfico.

SELECT
  DATE_TRUNC('month', order_ts) AS month,
  SUM(amount)                   AS revenue
FROM orders
GROUP BY 1
ORDER BY 1;

EXTRACT vs DATE_TRUNC

Os entrevistadores exploram diretamente essa distinção. Ambas as funções extraem informações do período, mas respondem a perguntas diferentes.

  • EXTRACT(MONTH FROM ts) retorna o número 3 para qualquer mês de março, em todos os anos, sendo útil para analisar a sazonalidade.
  • DATE_TRUNC('month', ts) retorna o início específico do mês, mantendo os anos distintos, sendo útil para séries temporais.

Se você agrupar por EXTRACT(MONTH ...) em um gráfico de tendência mensal, os anos serão silenciosamente combinados.

-- Seasonality: which month is busiest on average?
SELECT EXTRACT(MONTH FROM order_ts) AS month_num, COUNT(*)
FROM orders GROUP BY 1 ORDER BY 1;

-- Time series: month-by-month trend (years kept separate)
SELECT DATE_TRUNC('month', order_ts) AS month, COUNT(*)
FROM orders GROUP BY 1 ORDER BY 1;

Agrupamentos semanais e a questão da segunda-feira

O agrupamento semanal esconde uma sutileza que os entrevistadores gostam de explorar: quando começa a semana? O DATE_TRUNC('week', ts) do PostgreSQL sempre ajusta a data para segunda-feira (semanas ISO).

Se a empresa quiser semanas iniciadas no domingo, será necessário aplicar um deslocamento. Um recurso comum é retroceder a data em um dia, truncá-la e depois avançar um dia.

-- ISO week (Monday start)
SELECT DATE_TRUNC('week', order_ts) AS iso_week FROM orders;

-- Sunday-start week
SELECT DATE_TRUNC('week', order_ts + INTERVAL '1 day') - INTERVAL '1 day'
  AS sunday_week
FROM orders;

Agrupamentos por trimestre

Relatórios trimestrais são comuns em funções relacionadas à área financeira. DATE_TRUNC('quarter', ts) mapeia qualquer carimbo de data e hora para o primeiro dia do seu trimestre: 1º de janeiro, 1º de abril, 1º de julho ou 1º de outubro.

Para rotular o trimestre como um número, combine EXTRACT(QUARTER ...) com o ano.

SELECT
  DATE_TRUNC('quarter', order_ts)                  AS quarter_start,
  EXTRACT(YEAR FROM order_ts) || '-Q'
    || EXTRACT(QUARTER FROM order_ts)              AS quarter_label,
  SUM(amount)                                      AS revenue
FROM orders
GROUP BY 1, 2
ORDER BY 1;

O MySQL não tem DATE_TRUNC

Uma pergunta comum sobre diferentes dialetos é: “O MySQL não tem DATE_TRUNC; como você faria o agrupamento por mês?” A resposta portável é formatar a data até a granularidade desejada.

  • DATE_FORMAT(ts, '%Y-%m-01') fornece o início do mês como texto/data.
  • DATE_FORMAT(ts, '%Y-%m') fornece uma chave de texto ordenável, como 2024-03.

Para semanas, o MySQL oferece YEARWEEK() com um argumento de modo que controla o início da semana.

-- MySQL month bucket
SELECT DATE_FORMAT(order_ts, '%Y-%m-01') AS month, SUM(amount)
FROM orders
GROUP BY 1
ORDER BY 1;

Agrupamento no SQL Server

Historicamente, o SQL Server não tinha um truncamento direto, então os candidatos usavam DATEFROMPARTS ou o padrão DATEADD/DATEDIFF. As versões modernas (2022 ou posteriores) acrescentam DATETRUNC.

O padrão clássico, “contar unidades desde a época e depois adicioná-las novamente”, funciona em todas as versões e vale a pena conhecê-lo.

-- Portable SQL Server month truncation
SELECT DATEADD(month, DATEDIFF(month, 0, order_ts), 0) AS month_start
FROM orders;

-- SQL Server 2022+
SELECT DATETRUNC(month, order_ts) AS month_start FROM orders;

Preenchendo lacunas em uma série temporal

O truncamento, sozinho, elimina períodos sem linhas: um mês sem pedidos simplesmente não aparecerá. Os entrevistadores avaliam se você percebe isso.

A solução é gerar uma sequência completa de períodos e fazer um LEFT JOIN dos dados com ela. No PostgreSQL, generate_series cria essa sequência.

SELECT
  cal.month,
  COALESCE(SUM(o.amount), 0) AS revenue
FROM generate_series(DATE '2024-01-01', DATE '2024-12-01',
                      INTERVAL '1 month') AS cal(month)
LEFT JOIN orders o
  ON DATE_TRUNC('month', o.order_ts) = cal.month
GROUP BY cal.month
ORDER BY cal.month;

Exemplo mais aprofundado: usuários ativos por semana

Combine o agrupamento por períodos com a contagem de valores distintos. “Usuários ativos semanalmente” significa contar usuários distintos por intervalo semanal, uma solicitação real de análise de produto.

Trunque o carimbo de data e hora do evento para a semana e depois use COUNT(DISTINCT user_id). Mencionar que você juntaria uma sequência de semanas para exibir semanas sem atividade garante pontos extras.

SELECT
  DATE_TRUNC('week', event_ts) AS week,
  COUNT(DISTINCT user_id)      AS wau
FROM events
GROUP BY 1
ORDER BY 1;

Agrupando em uma coluna indexada

Vale mencionar uma ressalva de desempenho: envolver a coluna de data em DATE_TRUNC dentro de uma cláusula WHERE pode impedir que o planejador use um índice nessa coluna.

Isso é adequado em GROUP BY, mas, para filtrar, compare a coluna original com limites calculados. Já abordamos esse padrão semiaberto; ele também se aplica aqui.

-- Avoid in WHERE: DATE_TRUNC('month', order_ts) = '2024-03-01'
-- Prefer:
SELECT * FROM orders
WHERE order_ts >= DATE '2024-03-01'
  AND order_ts <  DATE '2024-04-01';

Verificação rápida

Escolha a ferramenta certa para um gráfico de tendência mensal que mantenha os anos separados.

Recapitulação: truncando e agrupando datas

O que você deve lembrar:

  • DATE_TRUNC(unit, ts) mapeia carimbos de data e hora para o início de um período e mantém os anos distintos, sendo a ferramenta certa para séries temporais.
  • EXTRACT retorna um número isolado, útil para sazonalidade, mas combina os anos.
  • As semanas no PostgreSQL começam na segunda-feira; aplique um deslocamento se precisar do domingo.
  • O MySQL usa DATE_FORMAT; versões antigas do SQL Server usam o padrão DATEADD(DATEDIFF(...)); as versões 2022 ou posteriores têm DATETRUNC.
  • Use uma sequência de datas + LEFT JOIN gerada para exibir períodos vazios e mantenha DATE_TRUNC fora de WHERE para preservar o uso de índices.

Perguntas Frequentes

A aula “Truncando e agrupando datas” é grátis?

Sim — o texto completo de “Truncando e agrupando datas” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de SQL Interview Prep, atualize para CoddyKit PRO. O curso de SQL Interview Prep inclui 4 aulas no total.

O que vou aprender em “Truncando e agrupando datas”?

Agrupando por semana, mês e trimestre com DATE_TRUNC e equivalentes. Você pratica SQL Interview Prep com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar SQL Interview Prep?

Nenhuma experiência prévia é necessária. SQL Interview Prep no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.

Quanto tempo leva a aula “Truncando e agrupando datas”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de SQL Interview Prep?

Sim. Cada aula de SQL Interview Prep inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Aritmética de datas e intervalos
  2. Truncando e agrupando datas
  3. Analisando e formatando strings
  4. Fusos horários e marcas de data e hora
← Voltar para SQL Interview Prep