Selo de estado:
Preview(teto atual do produto) · Curso ACD-310 — Modelo semântico e modelagem dimensional · Aula 5 de 10 · Atualizado em 2026-10-04.
Objetivo#
Ao final desta aula você vai aplicar papéis de relação (role-playing) num caso de datas múltiplas, ligar uma relação bidirecional sem criar ambiguidade e resolver uma relação N-N com tabela-ponte.
Vídeo#
Identificador no manifesto: acd-310-05-bidirecional-role-playing-ponte · duração-alvo 9 min · tela do produto: /dashboards.
Roteiro:
00:00–01:30— O problema das três datas: pedido, entrega, pagamento, uma só dimensãocalendario· tela:/dashboards/[id](diagrama, três relações paracalendario)01:30–03:30— Papéis de relação: uma ativa, duas inativas, nomeadas · tela:/dashboards/[id](editor de papéis da relação)03:30–05:00— Trocando o papel num visual sem reescrever a medida · tela:/dashboards/[id](visual, seletor "Data do Pedido" → "Data de Entrega")05:00–07:00— Filtro bidirecional opt-in:produtos↔vendascomcrossFilter: both· tela:/dashboards/[id](propriedades da relação, alternando "both")07:00–08:00— Ciclo e ambiguidade: por que o modelo recusa em vez de gerar SQL indefinido · tela:/dashboards/[id](segundo caminho de propagação, aviso de ambiguidade)08:00–09:00— Ponte M:N:produtos↔promocoesviaproduto_promocao, sem dupla contagem · tela:/dashboards/[id](diagrama com a tabela-ponte)
Conteúdo#
As aulas 3 e 4 cobriram a estrela básica, com uma relação por par de tabelas. Esta aula resolve três situações mais avançadas que aparecem o tempo todo em modelos reais de PME, todas descritas em Modelo semântico: múltiplas datas para o mesmo fato, filtro que precisa andar nos dois sentidos e relações muitos-para-muitos.
Papéis de relação (role-playing dimensions)
Quando um fato tem várias datas — pedido, entrega, pagamento — a tentação é criar três dimensões de calendário diferentes. Não é necessário: você liga a mesma dimensão calendario várias vezes ao fato, cada ligação com um papel nomeado.
No exemplo Aurora: vendas tem data_pedido, data_entrega e data_pagamento. Você cria três relações para calendario:
vendas.data_pedido → calendario.data, papel "Data do Pedido" — ativa.vendas.data_entrega → calendario.data, papel "Data de Entrega" — inativa.vendas.data_pagamento → calendario.data, papel "Data de Pagamento" — inativa.
Só uma relação por par de tabelas pode estar ativa ao mesmo tempo; as demais ficam inativas, mas disponíveis. O visual escolhe qual papel usar (FieldSpec.relationRole) em vez de você reescrever a medida para cada data — trocar de "Data do Pedido" para "Data de Entrega" num seletor muda o eixo do visual sem tocar em uma única fórmula. Papéis do mesmo par de tabelas formam automaticamente um grupo reconhecido pelo editor.
Nota
Há um teto de papéis por modelo (MAX_RELATION_ROLES). Para a Aurora, três papéis de data é um caso confortavelmente dentro do limite.
Filtro bidirecional (opt-in)
Por padrão, o filtro flui apenas do lado "um" para o lado "muitos": escolher uma categoria em produtos recorta as vendas daquela categoria — nunca o contrário. Isso cobre a maioria dos casos, mas às vezes você precisa que filtrar o fato também recorte a dimensão — por exemplo, mostrar na lista só os produtos que tiveram venda no período filtrado.
Para isso existe crossFilter: "both", que liga a propagação do filtro nos dois sentidos numa relação específica. Dois detalhes importam:
- O grafo de join (o SQL físico) é não-direcionado e não muda ao ligar "both" — o que muda é só o grafo de filtro.
- O modelo detecta ciclo e ambiguidade de propagação. Se dois caminhos bidirecionais entre as mesmas tabelas tornassem o resultado indefinido, o modelo recusa em vez de gerar um SQL ambíguo em silêncio.
É opt-in por relação: ativar "both" numa relação de produtos ↔ vendas não muda nada nas demais relações do modelo — um modelo todo "single" permanece exatamente como estava.
Relação M:N por ponte explícita
A última peça é a relação muitos-para-muitos. No Aurora, produtos pode estar em várias promocoes, e uma promocao pode ter vários produtos — um caso clássico de N-N, resolvido por uma tabela-ponte com chave estrangeira para as duas pontas: produto_promocao.
Ao cruzar produtos → produto_promocao → promocoes, a medida do lado oposto é deduplicada: a ponte é reduzida a pares distintos antes de somar, para que cada produto conte uma vez por valor de dimensão, não uma vez por linha da ponte. Uma medida que vive na própria ponte soma direto, porque o grão dela já é a ponte.
Com dados sintéticos: se produto_promocao tiver as linhas (10→"Julho"), (10→"Inverno") e (11→"Julho"), somar produtos.preco cruzando pela ponte não deve triplicar o produto 10 — ele aparece uma vez por promoção da qual faz parte, não três vezes só porque a ponte tem três linhas.
Aviso
Sem uma ponte explícita declarada, uma relação N-N é tratada como ambígua e recusada — o modelo nunca tenta "adivinhar" uma resolução para muitos-para-muitos.
Como escolher, na prática
| Situação | O que usar |
|---|---|
| Dúvida, caso comum | 1-N do fato para a dimensão, direção single. Cobre a maioria dos casos. |
| Filtrar o fato precisa recortar a dimensão | Bidirecional (both) — e confirme que o editor não acusou ambiguidade. |
| Várias datas/chaves para a mesma dimensão | Papéis de relação. |
| Qualquer N-N | Tabela-ponte — nunca force um N-N sem ela. |
Erros comuns
- Deixar duas relações ativas para a mesma dimensão. O modelo aceita só uma ativa por par de tabelas; as outras precisam ficar inativas e nomeadas como papel.
- Ligar "both" em cadeia sem checar ciclo. Ativar bidirecional em várias relações entre as mesmas tabelas é a receita para a ambiguidade que o editor recusa.
- Tentar forçar N-N sem ponte "porque funcionou visualmente". Mesmo que o diagrama pareça aceitar, o modelo trata isso como ambíguo e a agregação é recusada — a correção é sempre declarar a ponte.
Faça você mesmo#
No workspace de treino Aurora Varejo (abra /dashboards no console, editor de um painel, aba do modelo):
- Localize (ou crie) as três colunas de data em
vendas:data_pedido,data_entrega,data_pagamento. - Ligue
vendas.data_pedido → calendario.datae deixe como relação ativa, papel "Data do Pedido". - Ligue
vendas.data_entrega → calendario.datacomo inativa, papel "Data de Entrega". - Ligue
vendas.data_pagamento → calendario.datacomo inativa, papel "Data de Pagamento". - Em um visual existente, troque o papel usado de "Data do Pedido" para "Data de Entrega" e confirme que o eixo muda sem alterar a medida.
- Na relação
produtos↔vendas, ativecrossFilter: bothe filtrevendaspor um período recente; confirme que a lista deprodutosexibida se recorta também. - (Opcional) Se o seu workspace tiver uma tabela de promoções, declare a ponte
produto_promocaoe confirme que somarprodutos.precopela ponte não duplica o produto.
Você terminou quando conseguir trocar o papel de data num visual sem editar fórmula nenhuma, e explicar por que a relação bidirecional precisou ser conferida contra ciclo/ambiguidade antes de ativar.
Checagem rápida#
Três perguntas no final da aula, corrigidas no servidor. A aula só conta como concluída depois da checagem.
Documentação relacionada#
Capacidades ensinadas#
C05.2 · C05.3 · C05.4 — o selo exibido na aula é sempre o estado mais conservador entre as capacidades citadas; nada aqui é "GA".