(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa
Data Warehouse
Data Warehouse 4 min

Como criar uma dimensão de data num Data Warehouse

João Barros 04 de July de 2026 4 min de leitura

Quase todos os relatórios de BI filtram ou agrupam por tempo — por ano, por mês, por trimestre. Ter uma dimensão de data (uma tabela de calendário) no Data Warehouse é a maneira mais limpa e rápida de o conseguir, em vez de calcular datas repetidamente em cada consulta. A seguir vês, passo a passo, como criar uma dimensão de data em SQL e preenchê-la com um script simples e reutilizável.

Pré-requisitos

  • Uma base de dados SQL Server ou Azure SQL (o conceito aplica-se a qualquer Data Warehouse SQL).
  • Permissões para criar esquemas e tabelas (CREATE TABLE).
  • Noções básicas de SQL (CREATE, INSERT, SELECT).

Passo 1: Perceber o que é uma dimensão de data

Uma dimensão de data tem uma linha por dia e várias colunas descritivas: ano, mês, nome do mês, trimestre, dia da semana e um indicador de fim de semana. A chave da tabela costuma ser um número inteiro no formato AAAAMMDD (por exemplo, 20260704), a que se chama chave substituta (surrogate key). É pequena, ordenável e fácil de ligar às tuas tabelas de factos.

Como criar uma dimensão de data num Data Warehouse

Passo 2: Criar a tabela

Começamos por criar um esquema dim (opcional, mas ajuda a organizar) e a tabela que vai guardar o calendário. Dá a cada coluna o tipo mais pequeno que chegue — um detalhe simples que poupa espaço numa tabela com milhares de linhas.

CREATE SCHEMA dim;
GO

CREATE TABLE dim.Data (
    DataKey     int         NOT NULL PRIMARY KEY,
    Data        date        NOT NULL,
    Ano         smallint    NOT NULL,
    Trimestre   tinyint     NOT NULL,
    Mes         tinyint     NOT NULL,
    Dia         tinyint     NOT NULL,
    NomeMes     varchar(20) NOT NULL,
    DiaSemana   tinyint     NOT NULL,
    NomeDia     varchar(20) NOT NULL,
    FimDeSemana bit         NOT NULL
);

Passo 3: Gerar as datas com um CTE recursivo

Para preencher a tabela precisamos de uma linha por dia entre duas datas. Um CTE recursivo gera essa sequência sem precisares de tabelas auxiliares. Define o intervalo (por exemplo, de 2015 a 2035) e deixa o SQL contar os dias um a um.

DECLARE @Inicio date = '2015-01-01';
DECLARE @Fim    date = '2035-12-31';

WITH Calendario AS (
    SELECT @Inicio AS Data
    UNION ALL
    SELECT DATEADD(DAY, 1, Data)
    FROM Calendario
    WHERE Data < @Fim
)
SELECT Data FROM Calendario
OPTION (MAXRECURSION 0);
Erro comum: por omissão, o SQL Server pára um CTE recursivo aos 100 níveis e devolve o erro "maximum recursion". A cláusula OPTION (MAXRECURSION 0) remove esse limite.

Passo 4: Inserir os dados com colunas calculadas

Agora combinamos o CTE com funções de data para preencher todas as colunas. Repara em duas boas práticas: a chave DataKey é criada com o estilo 112 (formato AAAAMMDD) e o dia da semana é calculado com uma fórmula que não depende das definições de idioma do servidor (@@DATEFIRST), devolvendo sempre segunda-feira = 1.

SET LANGUAGE Portuguese;

DECLARE @Inicio date = '2015-01-01';
DECLARE @Fim    date = '2035-12-31';

WITH Calendario AS (
    SELECT @Inicio AS Data
    UNION ALL
    SELECT DATEADD(DAY, 1, Data)
    FROM Calendario
    WHERE Data < @Fim
)
INSERT INTO dim.Data
    (DataKey, Data, Ano, Trimestre, Mes, Dia, NomeMes, DiaSemana, NomeDia, FimDeSemana)
SELECT
    CAST(CONVERT(char(8), Data, 112) AS int)              AS DataKey,
    Data,
    YEAR(Data)                                            AS Ano,
    DATEPART(QUARTER, Data)                               AS Trimestre,
    MONTH(Data)                                           AS Mes,
    DAY(Data)                                             AS Dia,
    DATENAME(MONTH, Data)                                 AS NomeMes,
    ((@@DATEFIRST + DATEPART(WEEKDAY, Data) - 2) % 7) + 1 AS DiaSemana,
    DATENAME(WEEKDAY, Data)                               AS NomeDia,
    CASE WHEN ((@@DATEFIRST + DATEPART(WEEKDAY, Data) - 2) % 7) + 1 >= 6
         THEN 1 ELSE 0 END                                AS FimDeSemana
FROM Calendario
OPTION (MAXRECURSION 0);

O SET LANGUAGE Portuguese; faz com que DATENAME devolva os nomes em português ("janeiro", "segunda-feira"). Se preferires outro idioma, muda apenas esta linha.

Verificar o resultado

Confirma que a carga correu bem com duas consultas rápidas: uma para ver as primeiras linhas e outra para contar os dias e detetar duplicados.

SELECT TOP 10 * FROM dim.Data ORDER BY DataKey;

SELECT COUNT(*)              AS TotalDias,
       COUNT(DISTINCT DataKey) AS ChavesUnicas,
       MIN(Data)               AS Inicio,
       MAX(Data)               AS Fim
FROM dim.Data;

Se TotalDias for igual a ChavesUnicas, não há duplicados. Para o intervalo de 2015 a 2035 deves obter 7 670 linhas.

Conclusão

Com uma dimensão de data pronta, as tuas medidas de tempo (year-to-date, comparações homólogas, filtros por trimestre) ficam muito mais simples e rápidas. O próximo passo é ligar a coluna DataKey às tabelas de factos e, se usares Power BI, marcar esta tabela como "tabela de datas" para ativar a time intelligence. Que outros atributos fazem sentido no teu negócio — feriados, semana fiscal, época alta?

Partilhar: