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

Como criar uma factless fact table no data warehouse

João Barros 11 de July de 2026 4 min de leitura

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"?