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

Como criar uma tabela de factos num Data Warehouse

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

A tabela de factos é o coração de qualquer Data Warehouse: guarda os números que o negócio quer medir, como vendas, quantidades ou custos. Uma tabela de factos bem desenhada é o que transforma dados dispersos num modelo pronto para relatórios rápidos e fiáveis, e o segredo está em acertar no grão e nas chaves.

Pré-requisitos

  • Um servidor de base de dados (usamos SQL Server, mas a ideia aplica-se a qualquer motor).
  • Pelo menos duas dimensões já criadas (por exemplo, DimData e DimProduto).
  • Noções básicas de SQL (CREATE TABLE e INSERT).
  • Uma ferramenta para correr queries, como o SQL Server Management Studio ou o Azure Data Studio.

Passo 1: Definir o grão da tabela de factos

O grão é a pergunta mais importante: "o que representa uma linha desta tabela?". Antes de escrever qualquer SQL, decide o nível de detalhe. Neste exemplo, o grão é "uma linha por produto vendido em cada transação". Um grão claro evita erros de contagem e duplicação mais tarde.

Passo 2: Identificar as dimensões e as medidas

Com o grão definido, separa as colunas em dois grupos. As chaves estrangeiras ligam a tabela de factos às dimensões (quem, o quê, quando). As medidas são os valores numéricos que vais somar ou calcular. A maioria das medidas é aditiva, ou seja, pode ser somada com segurança em todas as dimensões. No nosso caso de vendas:

  • Chaves: DataKey, ProdutoKey, ClienteKey.
  • Medidas: Quantidade, ValorVenda, Desconto.

Passo 3: Criar a tabela de factos em SQL

Agora traduzimos o desenho para uma instrução CREATE TABLE. Cada chave estrangeira aponta para a chave substituta (surrogate key) da dimensão correspondente, e as medidas usam tipos numéricos com casas decimais para valores monetários.

CREATE TABLE FactVendas (
    VendaID      BIGINT IDENTITY(1,1) PRIMARY KEY,
    DataKey      INT NOT NULL,
    ProdutoKey   INT NOT NULL,
    ClienteKey   INT NOT NULL,
    Quantidade   INT NOT NULL,
    ValorVenda   DECIMAL(12,2) NOT NULL,
    Desconto     DECIMAL(12,2) NOT NULL DEFAULT 0,
    CONSTRAINT FK_Vendas_Data
        FOREIGN KEY (DataKey) REFERENCES DimData(DataKey),
    CONSTRAINT FK_Vendas_Produto
        FOREIGN KEY (ProdutoKey) REFERENCES DimProduto(ProdutoKey),
    CONSTRAINT FK_Vendas_Cliente
        FOREIGN KEY (ClienteKey) REFERENCES DimCliente(ClienteKey)
);

Passo 4: Carregar dados com as chaves das dimensões

A tabela de factos nunca guarda texto como "Lisboa" ou "Teclado"; guarda a chave numérica que veio da dimensão. Por isso, ao carregar, fazes JOIN entre os dados de origem e cada dimensão para ir buscar a chave certa. O exemplo seguinte insere uma venda já com as chaves resolvidas:

INSERT INTO FactVendas (DataKey, ProdutoKey, ClienteKey, Quantidade, ValorVenda, Desconto)
SELECT d.DataKey, p.ProdutoKey, c.ClienteKey, 3, 149.70, 0
FROM   DimData    d
JOIN   DimProduto p ON p.CodigoProduto = 'TEC-001'
JOIN   DimCliente c ON c.Email = 'ana@exemplo.pt'
WHERE  d.DataCompleta = '2026-07-04';

Repara que não há colunas descritivas na tabela de factos: tudo o que é "quem" e "o quê" vive nas dimensões.

Passo 5: Melhorar o desempenho com um índice

As consultas de BI filtram e agrupam quase sempre pelas chaves das dimensões. Criar um índice nessas colunas ajuda o motor a encontrar as linhas certas sem ler a tabela toda, o que é essencial quando a tabela de factos cresce para milhões de linhas.

CREATE INDEX IX_FactVendas_Data
    ON FactVendas (DataKey);

CREATE INDEX IX_FactVendas_Produto
    ON FactVendas (ProdutoKey);

Verificar o resultado

Para confirmar que a carga correu bem, conta as linhas e valida que todas as chaves têm correspondência nas dimensões. Uma tabela de factos saudável não tem chaves órfãs:

SELECT COUNT(*) AS TotalLinhas,
       SUM(ValorVenda) AS TotalVendido
FROM   FactVendas;

-- Procurar chaves sem dimensao (deve devolver 0 linhas)
SELECT f.VendaID
FROM   FactVendas f
LEFT JOIN DimProduto p ON p.ProdutoKey = f.ProdutoKey
WHERE  p.ProdutoKey IS NULL;

Se a segunda query não devolver linhas, todas as vendas apontam para produtos válidos.

Conclusão

Criaste uma tabela de factos ligada às dimensões por chaves e pronta para alimentar relatórios em Power BI ou qualquer ferramenta de BI. O próximo passo natural é automatizar a carga com um processo ETL e vigiar o grão à medida que chegam novas fontes. Qual vai ser a primeira medida que a tua equipa vai querer analisar?