Como criar uma factless fact table no data warehouse
Uma tabela de factos sem factos (em inglês, factless fact table) é uma tabela de factos que não guarda medidas numéricas — apenas as chaves estrangeiras que ligam às dimensões. À primeira vista parece um contrassenso ter uma tabela de factos "vazia", mas é a forma mais elegante de registar que um evento aconteceu (uma presença, um clique, uma inscrição) e de responder a perguntas sobre contagens e, sobretudo, sobre o que não aconteceu.
Pré-requisitos
- Um data warehouse ou base de dados relacional (os exemplos usam SQL Server, mas o padrão é igual em qualquer motor).
- Noções básicas de modelação dimensional: o que são dimensões, factos e o esquema em estrela.
- Permissões para criar tabelas e inserir dados.
Passo 1: Perceber quando usar
Existem dois cenários clássicos para este padrão. O primeiro é o registo de eventos: cada linha diz que algo ocorreu num determinado momento — um aluno esteve presente numa aula, um utilizador viu uma página, um cartão foi validado à entrada. O segundo é a cobertura (ou elegibilidade): a tabela regista relações que poderiam acontecer, para que seja possível medir o que não aconteceu. Sem estas linhas é impossível responder a "quem faltou?", porque uma ausência não gera, por natureza, nenhum registo.
Passo 2: Modelar as dimensões
Vamos usar o exemplo de presenças em aulas. Precisamos de três dimensões: o aluno, a turma e a data. Assumimos que já existem no modelo, cada uma com a sua chave substituta (surrogate key).
-- Dimensões (simplificadas)
CREATE TABLE DimAluno (
AlunoKey INT PRIMARY KEY,
Nome NVARCHAR(100)
);
CREATE TABLE DimTurma (
TurmaKey INT PRIMARY KEY,
Disciplina NVARCHAR(100)
);
CREATE TABLE DimData (
DataKey INT PRIMARY KEY, -- ex.: 20260711
Data DATE
);
Passo 3: Criar a tabela de factos sem factos
A tabela de presenças contém apenas chaves. Não há colunas de quantidade nem de valor — daí o nome "sem factos". O grão (o nível de detalhe de cada linha) é claro: uma linha por aluno, por turma e por dia. Cada linha representa, portanto, uma presença confirmada.
CREATE TABLE FactPresenca (
AlunoKey INT NOT NULL REFERENCES DimAluno(AlunoKey),
TurmaKey INT NOT NULL REFERENCES DimTurma(TurmaKey),
DataKey INT NOT NULL REFERENCES DimData(DataKey),
CONSTRAINT PK_FactPresenca PRIMARY KEY (AlunoKey, TurmaKey, DataKey)
);
Dica: alguns modeladores acrescentam uma coluna constante com o valor 1 (por exemplo Presencas) para simplificar as somas. É opcional; contar linhas dá exatamente o mesmo resultado.
Passo 4: Carregar alguns dados
INSERT INTO FactPresenca (AlunoKey, TurmaKey, DataKey) VALUES
(1, 10, 20260711),
(2, 10, 20260711),
(3, 10, 20260711);
Estas três linhas dizem que os alunos 1, 2 e 3 estiveram presentes na turma 10 no dia 11 de julho de 2026.
Passo 5: Contar eventos
Para saber quantos alunos assistiram a cada aula, contamos as linhas. Como não há nenhuma medida para somar, usamos COUNT(*) em vez de SUM — é esta a diferença fundamental em relação a uma tabela de factos tradicional.
SELECT t.Disciplina,
d.Data,
COUNT(*) AS TotalPresencas
FROM FactPresenca f
JOIN DimTurma t ON t.TurmaKey = f.TurmaKey
JOIN DimData d ON d.DataKey = f.DataKey
GROUP BY t.Disciplina, d.Data;
Passo 6: Responder às ausências com cobertura
Aqui está o verdadeiro poder do padrão. Para saber quem faltou, precisamos de saber quem deveria ter estado presente. Uma segunda tabela sem factos — de cobertura — regista as inscrições: que aluno está inscrito em que turma.
-- Cobertura: inscrições (quem deveria comparecer)
CREATE TABLE FactInscricao (
AlunoKey INT NOT NULL,
TurmaKey INT NOT NULL,
CONSTRAINT PK_FactInscricao PRIMARY KEY (AlunoKey, TurmaKey)
);
Com um LEFT JOIN entre inscritos e presentes, as linhas sem correspondência revelam as ausências de um dia:
SELECT i.AlunoKey
FROM FactInscricao i
LEFT JOIN FactPresenca p
ON p.AlunoKey = i.AlunoKey
AND p.TurmaKey = i.TurmaKey
AND p.DataKey = 20260711
WHERE i.TurmaKey = 10
AND p.AlunoKey IS NULL;
Verificar o resultado
Se o aluno 4 estiver inscrito na turma 10 mas não tiver linha em FactPresenca para o dia 11, a última consulta devolve o seu AlunoKey. Confirme ainda que a contagem do Passo 5 corresponde ao número de linhas inseridas — três presenças para a turma 10. Se ambos os números baterem certo, o modelo está correto.
Conclusão
Uma tabela de factos sem factos resolve, de forma simples, dois problemas que de outra maneira seriam complicados: contar eventos e medir o que não aconteceu. O próximo passo é aplicar o mesmo padrão a outros domínios — cliques em campanhas, promoções ativas por loja ou visitas a páginas. Fica a pergunta: que evento importante do seu negócio ainda não está a ser registado só porque "não tem nenhuma medida para guardar"?