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

Como criar uma Fact table de tipo 'Periodic Snapshot' em Modelação de Dados (Kimball)

João Barros 16 de August de 2026 4 min de leitura

Este tutorial ensina a criar uma Fact table do tipo Periodic Snapshot em Modelação de Dados (Kimball) para armazenar métricas periódicas (por exemplo, saldo diário de conta). A Periodic Snapshot é útil para relatórios de tendência e reconciliação quando os eventos não capturam o estado em cada período.

Pré-requisitos

  • Conhecimentos básicos de SQL (SELECT, JOIN, GROUP BY).
  • Entendimento de conceitos Kimball: fact tables, dimension tables, chaves surrogate.
  • Uma base de dados para testes (ex.: SQL Server, PostgreSQL) com tabelas de origem.

Passo 1: Definir o objetivo e a granularidade

Explique por que precisa de uma Periodic Snapshot: quer registar o estado no final de cada dia, semana ou mês? A granularidade determina as dimensões da fact e a frequência de carga. Decida também quais métricas são snapshots (por exemplo, saldo, número de utilizadores activos) e quais são acumuladas.

Passo 2: Identificar dimensões e chave de grain

Escolha as dimensões que descrevem o grain. Para um snapshot diário de conta, o grain pode ser: um registo por data + account_id. As dimensões comuns: DimDate, DimAccount, DimBranch, DimProduct. Crie ou confirme as surrogate keys das dimensões.

Passo 3: Esquema da Periodic Snapshot fact table

Defina colunas: surrogate keys para dimensões, snapshot_date, métricas (saldo, número de transacções no dia) e indicadores (flags). Inclua colunas de auditoria (load_date, source_system).

CREATE TABLE FactAccountDailySnapshot (
  FactSnapshotSK BIGINT IDENTITY(1,1) PRIMARY KEY,
  DateSK INT NOT NULL,
  AccountSK INT NOT NULL,
  BranchSK INT NULL,
  SnapshotDate DATE NOT NULL,
  Balance DECIMAL(18,2) NULL,
  DailyTxCount INT NULL,
  LoadDate DATETIME NOT NULL DEFAULT GETDATE(),
  SourceSystem VARCHAR(50) NULL
);

Passo 4: Mapear fontes e calcular estado por período

Identifique as tabelas fonte e a lógica para calcular o estado no fim do período. Por exemplo, calcular o saldo diário pode somar transacções até ao fim do dia ou usar uma coluna de saldo corrente se existir.

-- Exemplo: calcular saldo por account no fim do dia somando transacções
WITH TxUntilDay AS (
  SELECT
    account_id,
    CAST(transaction_date AS DATE) AS txn_date,
    SUM(amount) AS day_amount
  FROM StgTransactions
  WHERE transaction_date <= @SnapshotDate + '23:59:59'
  GROUP BY account_id, CAST(transaction_date AS DATE)
)
SELECT a.account_id, d.DateSK, a.AccountSK,
       ISNULL(t.day_amount,0) AS Balance -- simplificação de exemplo
FROM DimAccount a
CROSS JOIN (SELECT @SnapshotDate AS SnapshotDate, DateSK FROM DimDate WHERE FullDate = @SnapshotDate) d
LEFT JOIN TxUntilDay t ON t.account_id = a.account_id AND t.txn_date = @SnapshotDate;

Passo 5: Estratégia de carga (ETL/ELT)

Decida se faz carga completa diária (recria os registos desse dia) ou incremental (apaga/regenera por grain). A abordagem mais segura para snapshots é carregar por período: eliminar registos de SnapshotDate e grain e inserir os novos. Automatize com transacções para atomicidade.

BEGIN TRANSACTION;
  DELETE FROM FactAccountDailySnapshot
  WHERE SnapshotDate = @SnapshotDate;

  INSERT INTO FactAccountDailySnapshot (DateSK, AccountSK, BranchSK, SnapshotDate, Balance, DailyTxCount, SourceSystem)
  SELECT d.DateSK, a.AccountSK, a.BranchSK, @SnapshotDate, t.Balance, t.DailyTxCount, 'OLTP'
  FROM (... cálculo anterior ...) t
  JOIN DimAccount a ON a.account_id = t.account_id
  JOIN DimDate d ON d.FullDate = @SnapshotDate;
COMMIT;

Passo 6: Lidar com erros comuns

Erros frequentes: 1) grain mal definido (duplicados por SnapshotDate/account); 2) não utilizar surrogate keys das dimensões; 3) carga parcial sem limpeza causando valores antigos; 4) performance na junção com tabelas grandes. Para evitar, implemente constraints de unicidade (DateSK+AccountSK+SnapshotDate), índices e partição por SnapshotDate se suportado.

ALTER TABLE FactAccountDailySnapshot
ADD CONSTRAINT UQ_FactSnapshot_Date_Account UNIQUE (DateSK, AccountSK, SnapshotDate);

-- Índice para melhorar consultas por data
CREATE INDEX IX_FactAccountDailySnapshot_SnapshotDate ON FactAccountDailySnapshot(SnapshotDate);

Verificar o resultado

Valide integridade e valores: 1) confirmar unicidade por grain; 2) reconciliar somas agregadas com sistemas fonte para várias datas; 3) testar query de tendência (ex.: saldo por account nos últimos 30 dias). Exemplos de checks em SQL:

-- 1. Verificar duplicados
SELECT DateSK, AccountSK, SnapshotDate, COUNT(*)
FROM FactAccountDailySnapshot
GROUP BY DateSK, AccountSK, SnapshotDate
HAVING COUNT(*) > 1;

-- 2. Reconciliar total de saldo (amostra)
SELECT f.SnapshotDate, SUM(f.Balance) AS TotalBalance
FROM FactAccountDailySnapshot f
WHERE f.SnapshotDate BETWEEN '2026-07-01' AND '2026-07-31'
GROUP BY f.SnapshotDate
ORDER BY f.SnapshotDate;

Conclusão

Uma Periodic Snapshot em Modelação de Dados (Kimball) captura estados regulares para análises de tendência e auditoria. Próximos passos: agregar outras métricas, particionar a tabela para escala e automatizar a carga com um scheduler. Dica: começa com cargas diárias em ambiente de teste e verifica sempre as reconciliações antes de produção — qual métrica queres capturar primeiro?