Dimensões role-playing no star schema: passo a passo
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?