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

Como criar uma Dimension Degenerate (Degenerate Dimension) em Modelação de Dados (Kimball)

João Barros 09 de September de 2026 4 min de leitura

Este tutorial mostra como criar uma Dimension Degenerate (degenerada) seguindo os princípios Kimball: quando e porque manter atributos de transacção directamente na fact table em vez de criar uma dimensão separada. Aprender a modelar degenerate dimensions ajuda a simplificar consultas e a reduzir joins desnecessários em cenários de faturas, pedidos ou transacções únicas.

Pré-requisitos

  • Conhecimentos básicos de SQL (SELECT, JOIN, INSERT).
  • Compreensão do conceito de star schema e de fact/dimension.
  • Uma base de dados de teste (por exemplo SQL Server, PostgreSQL ou MySQL).

Passo 1: Identificar quando usar uma Degenerate Dimension

Uma Degenerate Dimension é um atributo ligado à transacção que não necessita de identidade ou atributos adicionais que justifiquem uma dimensão separada. Exemplos típicos: número de fatura, código de transacção, referência externa. Use-a quando o atributo é único por linha de fact e não vai ser partilhado entre fact tables.

Passo 2: Verificar requisitos de consulta e granularidade

Antes de decidir manter o campo na fact table, confirme que os relatórios não precisam de atributos adicionais, histórico ou conformidade que exigiriam uma dimensão. Pense em performance: se muitos relatórios só filtram por esse campo, uma Degenerate Dimension (na fact) reduz joins.

Passo 3: Definir a estrutura da fact table com a Degenerate Dimension

Crie a fact table incluindo a chave da fact (surrogate key ou natural), medidas e o campo degenerado como coluna não referenciada a uma dimensão. Garanta o tipo de dados adequado e indexação quando necessário para filtros frequentes.

-- Exemplo em SQL (SQL Server sintaxe genérica)  CREATE TABLE FactSales (
  SaleID BIGINT PRIMARY KEY,       -- surrogate key da fact
  InvoiceNumber VARCHAR(50) NOT NULL, -- Degenerate Dimension
  CustomerKey INT NOT NULL,         -- FK para Dimension Customer
  ProductKey INT NOT NULL,          -- FK para Dimension Product
  SaleDateKey INT NOT NULL,         -- FK para Dimension Date
  Quantity INT,
  Amount DECIMAL(18,2)
);

-- Índice para procurar por InvoiceNumber rapidamente
CREATE INDEX IX_FactSales_InvoiceNumber ON FactSales(InvoiceNumber);

Passo 4: Carga ETL/ELT: povoar a Degenerate Dimension

No processo ETL/ELT, apenas mapeie o valor do campo de transacção directamente para a coluna da fact. Não tente criar uma surrogate key separada. Trate duplicados e normalização apenas se necessário para garantir integridade (ex.: limpeza de espaços, formato consistente).

-- Exemplo simples de INSERT durante ETL  INSERT INTO FactSales (SaleID, InvoiceNumber, CustomerKey, ProductKey, SaleDateKey, Quantity, Amount)
SELECT
  s.SourceSaleID, -- pode ser surrogate gerado
  TRIM(s.InvoiceNo),
  d.CustomerKey,
  p.ProductKey,
  dd.DateKey,
  s.Quantity,
  s.TotalAmount
FROM StagingSales s
JOIN DimCustomer d ON s.CustomerID = d.CustomerID
JOIN DimProduct p ON s.ProductCode = p.ProductCode
JOIN DimDate dd ON CAST(s.SaleDate AS DATE) = dd.FullDate
WHERE s.IsActive = 1;

Passo 5: Tratar erros comuns

Erros comuns: 1) Tratar InvoiceNumber como dimensão e depois descobrir que é única por linha — cria redundância. 2) Não indexar InvoiceNumber quando usado em filtros — consultas lentas. 3) Assumir imutabilidade quando os números podem mudar (ex.: correcção de fatura) — definir política: actualizar a fact ou criar evento de correcção.

Verificar o resultado

Confirme que a Degenerate Dimension funciona executando consultas reais: filtragem por InvoiceNumber, agregações por Customer e verificação dos planos de execução. Testes a realizar:

  • SELECT por InvoiceNumber — deve devolver a linha correcta e ser rápido.
  • Contagens de invoices distintos — comparar com a origem.
  • Relatórios que agregam por Customer/Date — garantir que não há excesso de joins.
-- Exemplos de verificação
-- 1) Procurar fatura específica
SELECT * FROM FactSales WHERE InvoiceNumber = 'INV-2026-0001';

-- 2) Contar invoices distintos por dia
SELECT SaleDateKey, COUNT(DISTINCT InvoiceNumber) AS NumInvoices
FROM FactSales
GROUP BY SaleDateKey;

Conclusão

Manter uma Degenerate Dimension na fact table simplifica o modelo quando o atributo é único por transacção e não tem atributos próprios. Próximos passos: avaliar indexação, políticas de actualização e impacto em relatórios. Dica: documente sempre por que um campo é degenerado — isso poupará tempo à equipa quando estiverem a optimizar consultas.