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

Dimensões role-playing no star schema: passo a passo

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

Num data warehouse é comum uma tabela de factos guardar várias datas — a data da encomenda, a data de envio e a data prevista de entrega. Criar uma dimensão de data separada para cada uma multiplica a manutenção e abre a porta a inconsistências. As dimensões role-playing resolvem o problema: uma única dimensão, reutilizada em vários papéis dentro do mesmo star schema. O nome vem do teatro — o mesmo "ator" (a dimensão) entra em cena em papéis diferentes.

Pré-requisitos

  • Um data warehouse com uma dimensão de data (DimDate) já criada e com chave substituta (surrogate key).
  • Uma tabela de factos com mais do que uma data (por exemplo, FactSales).
  • Acesso a SQL Server ou motor equivalente e, para a segunda abordagem, a um modelo em Power BI.
  • Noções básicas de esquema em estrela (factos e dimensões).

Passo 1: Desenhar a tabela de factos com várias datas

Comece por garantir que a tabela de factos tem uma chave estrangeira para cada data relevante, todas a apontar para a mesma DimDate. Note que não existem três dimensões: existe uma só, referenciada várias vezes. As datas ainda por concretizar (envio, entrega) podem ficar a NULL até acontecerem.

CREATE TABLE FactSales (
    SalesKey     BIGINT IDENTITY(1,1) PRIMARY KEY,
    OrderDateKey INT NOT NULL,   -- FK to DimDate
    ShipDateKey  INT NULL,       -- FK to DimDate
    DueDateKey   INT NULL,       -- FK to DimDate
    ProductKey   INT NOT NULL,
    Quantity     INT NOT NULL,
    Amount       DECIMAL(18,2) NOT NULL
);

Passo 2: Manter uma só dimensão de data

Não duplique a DimDate. Uma única tabela — com uma linha por dia e colunas como CalendarYear, trimestre, mês e dia da semana — serve todos os papéis. Assim, "1.º trimestre" significa exatamente o mesmo seja qual for a data em análise, e a manutenção fica concentrada num só sítio.

Passo 3: Abordagem A — vistas por papel na base de dados

Quando o modelo é consumido diretamente por SQL, a forma mais clara é expor a mesma dimensão através de vistas com nomes falantes. Cada vista representa um papel da DimDate.

CREATE VIEW DimOrderDate AS SELECT * FROM DimDate;
GO
CREATE VIEW DimShipDate  AS SELECT * FROM DimDate;
GO
CREATE VIEW DimDueDate   AS SELECT * FROM DimDate;
GO

Cada junção passa a usar a vista correspondente, tornando a consulta imediata de ler:

SELECT od.CalendarYear AS OrderYear,
       SUM(f.Amount)   AS Sales
FROM FactSales AS f
JOIN DimOrderDate AS od ON od.DateKey = f.OrderDateKey
GROUP BY od.CalendarYear
ORDER BY od.CalendarYear;

Esta abordagem é simples e universal: qualquer ferramenta que leia SQL vê três dimensões com nomes distintos. A desvantagem é gerir mais objetos na base de dados, pelo que convém documentar que todas partilham a mesma DimDate.

Passo 4: Abordagem B — múltiplas relações no modelo semântico

Em Power BI ou Analysis Services, importe a DimDate uma só vez e crie uma relação para cada chave de data da tabela de factos. O motor só permite uma relação ativa entre duas tabelas; as restantes ficam inativas (a tracejado no diagrama). Isto evita ambiguidade: por omissão, o motor precisa de saber que caminho seguir entre as tabelas. A relação ativa costuma ser a da data da encomenda.

Para analisar por uma data inativa, ative a relação apenas dentro da medida, com USERELATIONSHIP:

Sales by Ship Date =
CALCULATE (
    SUM ( FactSales[Amount] ),
    USERELATIONSHIP ( FactSales[ShipDateKey], DimDate[DateKey] )
)

A medida de vendas normal continua a usar a data da encomenda; esta nova medida filtra pela data de envio, sem que seja preciso duplicar a dimensão.

Dica: dê nomes claros às medidas de cada papel — "Sales by Ship Date", "Sales by Due Date" — para que quem lê o relatório perceba logo qual a data em uso.

Verificar o resultado

Coloque as duas medidas lado a lado numa matriz, com os anos de DimDate nas linhas. Se os totais anuais diferirem entre a medida de encomenda e a de envio, os papéis estão a funcionar: cada um filtra por uma data distinta. Na abordagem SQL, compare o total agrupado por DimOrderDate com o mesmo agrupado por DimShipDate — os valores devem divergir sempre que a encomenda e o envio caírem em anos diferentes.

Conclusão

Com uma única dimensão de data reutilizada em vários papéis, o modelo fica mais simples, coerente e fácil de manter. A mesma técnica aplica-se a outras dimensões — por exemplo, um DimEmployee nos papéis de "vendedor" e de "aprovador". Qual das datas do seu negócio merecia já ter a sua própria medida?