(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa
Modelação de Dados (Kimball)
Modelação de Dados (Kimball) 2 min

Slowly Changing Dimensions Tipo 2: preservar histórico no data warehouse

João Barros 20 de March de 2025 2 min de leitura

As Slowly Changing Dimensions (SCD) resolvem um problema fundamental em data warehousing: o que fazer quando um atributo de uma dimensão muda? A resposta depende da necessidade de negócio de preservar o estado histórico.

Os 3 tipos principais

TIPO 1 — Sobrescrever (sem histórico):
  Antes: Cliente X — Segmento: PME
  Depois da mudança: Cliente X — Segmento: Enterprise
  → O passado parece sempre Enterprise. Bom para correcções de erros.

TIPO 2 — Novo registo (com histórico completo):
  Registo 1: Cliente X, Segmento PME,        valid_from: 2020-01-01, valid_to: 2023-12-31, is_current: 0
  Registo 2: Cliente X, Segmento Enterprise, valid_from: 2024-01-01, valid_to: 9999-12-31, is_current: 1
  → Análises históricas mostram PME nas vendas até 2023. O mais usado.

TIPO 3 — Coluna adicional (apenas último + anterior):
  Cliente X — Segmento_Actual: Enterprise, Segmento_Anterior: PME
  → Só preserva 1 mudança. Raro mas útil para reorganizações.

Implementar SCD Tipo 2 com MERGE

-- Processo ETL: aplicar alterações da fonte à dimensão
MERGE dbo.DimCliente AS tgt
USING (SELECT nk_cliente, nome, segmento, pais FROM stg.Clientes) AS src
    ON tgt.nk_cliente = src.nk_cliente AND tgt.is_current = 1

-- Tipo 1: actualizar atributos que não guardam histórico (nome - correcção de erro)
WHEN MATCHED AND tgt.nome <> src.nome
    THEN UPDATE SET tgt.nome = src.nome

-- Tipo 2: fechar registo actual e inserir novo
WHEN MATCHED AND tgt.segmento <> src.segmento
    THEN UPDATE SET tgt.valid_to = CAST(GETDATE() AS DATE), tgt.is_current = 0;

-- Inserir novos registos: clientes novos + versão nova dos SCD2
INSERT INTO dbo.DimCliente (nk_cliente, nome, segmento, pais, valid_from, valid_to, is_current)
SELECT src.nk_cliente, src.nome, src.segmento, src.pais,
       CAST(GETDATE() AS DATE), '9999-12-31', 1
FROM stg.Clientes src
LEFT JOIN dbo.DimCliente tgt ON src.nk_cliente = tgt.nk_cliente AND tgt.is_current = 1
WHERE tgt.sk_cliente IS NULL
   OR (tgt.sk_cliente IS NOT NULL AND tgt.segmento <> src.segmento);

Join correcto em relatórios

-- Para análise histórica correcta, usar a surrogate key da data da transacção
SELECT
    v.receita,
    c.segmento,  -- segmento do cliente NO MOMENTO da venda
    d.ano
FROM dbo.FactVendas   v
JOIN dbo.DimCliente   c ON v.sk_cliente = c.sk_cliente  -- SK preserva contexto histórico
JOIN dbo.DimData      d ON v.sk_data    = d.sk_data

Conclusão

SCD Tipo 2 é a espinha dorsal da análise histórica correcta. Sem ela, relatórios históricos mostram clientes com o segmento actual, não o que tinham quando compraram. A surrogate key é o mecanismo que preserva o contexto — nunca faça joins pela chave natural em factos históricos.

Partilhar: