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

Como implementar SCD Tipo 2 em ELT: passo a passo

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

Guardar o histórico de alterações de um cliente — como uma mudança de morada ou de segmento — é essencial para análises fiáveis ao longo do tempo. O padrão SCD Tipo 2 (Slowly Changing Dimension) resolve isto: cria uma nova versão do registo sempre que um atributo muda, em vez de substituir o valor antigo. Num fluxo ELT, os dados chegam primeiro à camada de staging e são transformados com SQL já dentro do data warehouse.

Pré-requisitos

  • Acesso a um data warehouse com SQL (SQL Server, Azure Synapse, Snowflake, Databricks ou BigQuery).
  • Uma tabela de staging com os dados atuais da origem (por exemplo, stg_clientes).
  • Noções básicas de SQL: INSERT, UPDATE e JOIN.
  • Permissões para criar e alterar tabelas no destino.

Passo 1: Perceber o que é uma dimensão SCD Tipo 2

Uma dimensão SCD Tipo 2 mantém várias linhas para a mesma entidade — por exemplo, um cliente — uma por cada período em que os seus dados foram válidos. Três colunas de controlo tornam isto possível: valid_from (início da validade), valid_to (fim da validade) e is_current (marca a versão ativa). Assim, uma consulta consegue saber qual era o segmento de um cliente em qualquer data do passado, algo impossível se apenas guardássemos o valor mais recente.

Passo 2: Criar a tabela de dimensão com colunas de histórico

Além dos atributos do negócio (nome, segmento), a tabela final precisa de uma chave substituta (surrogate key) e das três colunas de controlo. A coluna cliente_id guarda a chave de negócio que liga cada versão ao mesmo cliente real. Os exemplos usam sintaxe de SQL Server; a lógica é igual noutros warehouses.

CREATE TABLE dim_cliente (
    cliente_sk INT IDENTITY(1,1) PRIMARY KEY,
    cliente_id INT NOT NULL,
    nome VARCHAR(100),
    segmento VARCHAR(50),
    valid_from DATE NOT NULL,
    valid_to DATE NULL,
    is_current BIT NOT NULL
);

Passo 3: Fechar as versões antigas que mudaram

A primeira parte da transformação encontra os registos cujo nome ou segmento difere da versão que está no staging e "fecha-os": preenche o valid_to com a data de hoje e coloca is_current = 0. Só as linhas atuais que realmente mudaram são afetadas; as restantes ficam intactas.

UPDATE d
SET d.valid_to = CAST(GETDATE() AS DATE),
    d.is_current = 0
FROM dim_cliente AS d
INNER JOIN stg_clientes AS s
    ON s.cliente_id = d.cliente_id
WHERE d.is_current = 1
  AND (d.segmento <> s.segmento OR d.nome <> s.nome);

Passo 4: Inserir as novas versões

A seguir, inserimos uma linha nova para cada cliente que é novo ou que acabámos de fechar no passo anterior. A nova versão fica marcada como atual (is_current = 1), com valid_from a hoje e valid_to vazio.

INSERT INTO dim_cliente (cliente_id, nome, segmento, valid_from, valid_to, is_current)
SELECT s.cliente_id, s.nome, s.segmento, CAST(GETDATE() AS DATE), NULL, 1
FROM stg_clientes AS s
LEFT JOIN dim_cliente AS d
    ON d.cliente_id = s.cliente_id AND d.is_current = 1
WHERE d.cliente_id IS NULL;

O LEFT JOIN seguido de WHERE d.cliente_id IS NULL apanha dois casos ao mesmo tempo: clientes totalmente novos (nunca tiveram linha na dimensão) e clientes cuja versão atual foi fechada no Passo 3 — que, por isso, já não têm nenhuma linha com is_current = 1. Os clientes que não mudaram continuam com a sua linha atual e não são duplicados.

Passo 5: Automatizar a transformação no pipeline ELT

Junta os dois comandos numa única stored procedure ou script, executado sempre depois de carregar a camada de staging. A ordem é importante: primeiro o UPDATE que fecha, depois o INSERT que cria. Um orquestrador como o Azure Data Factory, o Databricks Workflows ou um simples agendador pode correr este passo a cada atualização de dados. Como o processo compara sempre o staging com a versão atual, correr o script duas vezes seguidas não cria duplicados: é idempotente.

Verificar o resultado

A regra de ouro de uma SCD Tipo 2 é simples: cada entidade só pode ter uma versão atual. A consulta seguinte não deve devolver nenhuma linha — se devolver, há um cliente com versões atuais a mais.

SELECT cliente_id, COUNT(*) AS versoes_atuais
FROM dim_cliente
WHERE is_current = 1
GROUP BY cliente_id
HAVING COUNT(*) > 1;

Para ver o histórico, consulta um cliente específico e ordena por valid_from: deverás ver uma linha fechada (com valid_to preenchido e is_current = 0) e uma linha atual. Isso confirma que a mudança foi guardada sem perder o valor anterior.

Conclusão

Com apenas dois comandos SQL — fechar as versões antigas e inserir as novas — já consegues manter um histórico fiável numa dimensão SCD Tipo 2 dentro de um fluxo ELT. A partir daqui, podes adicionar uma coluna de hash para detetar mudanças em muitos atributos de uma só vez, ou usar uma data de fim máxima (por exemplo 9999-12-31) em vez de NULL para simplificar as junções. Que atributos do teu negócio mudam com o tempo e mereciam ficar guardados em histórico?