Selo de estado:
Preview(teto atual do produto) · Curso ACD-220 — Pipelines e medalhão Bronze/Silver/Gold · Aula 9 de 12 · Atualizado em 2026-10-04.
Objetivo#
Ao final desta aula você vai construir Gold agregado sem fan-out — agrupar, cruzar tabelas declarando a cardinalidade e entender por que o produto bloqueia um cruzamento que multiplicaria suas linhas.
Vídeo#
Identificador no manifesto: acd-220-09-group-by-e-joins-sem-fan-out · duração-alvo 8 min · tela do produto: /sources.
Roteiro de gravação (5 capítulos):
| # | Minutagem-alvo | Capítulo | Tela do produto |
|---|---|---|---|
| 1 | 0:00–0:45 | Abertura: título + selo. O defeito clássico: "a receita triplicou e ninguém mexeu no dado". | /sources |
| 2 | 0:45–2:40 | Passo agrupar: chaves (a ordem é a ordem de saída), as seis agregações e os nomes de saída. | /sources |
| 3 | 2:40–4:40 | Passo juntar: segunda tabela, modo esquerda/interna, chaves do ON, lista de colunas do lado direito. | /sources |
| 4 | 4:40–6:40 | Cardinalidade esperada e o bloqueio de fan-out: a mensagem com a venda de 3 itens; quando aprovar explicitamente. | /sources |
| 5 | 6:40–8:00 | Montar gold.vendas_mensal_filial e conferir o total contra a Silver; encerramento com o "faça você mesmo". | /dados |
Conteúdo#
Um cruzamento errado não dá erro — dá número errado
Cruzar vendas com uma tabela que tem várias linhas por venda multiplica as suas linhas: uma venda com 3 itens vira 3 linhas, e soma(receita) triplica. Nenhum banco reclama disso. É por isso que o produto pede a cardinalidade esperada e bloqueia o cruzamento perigoso em vez de deixar você descobrir no painel.
agrupar: as chaves e as seis agregações
O passo agrupar tem duas partes:
- chaves — as colunas do agrupamento. A ordem é semântica: é a ordem das colunas de saída. Lista vazia = agregação global (uma linha só, sem agrupamento) — é assim que se monta um mart de KPI.
- agregações — uma ou mais, e a ordem define a ordem das colunas de saída.
| Agregação | O que faz | Observação |
|---|---|---|
soma | Soma a coluna | Infla com fan-out |
media | Média da coluna | Infla com fan-out |
contagem | Conta linhas; sem coluna = contar todas as linhas | Infla com fan-out |
contagem_distinta | Conta valores distintos | Segura sob fan-out |
min / max | Menor / maior valor | Seguras sob fan-out |
Cada agregação pode receber um nome de saída. Sem nome, ele é derivado (soma_valor, contagem). Um nome informado por você é validado como identificador simples — nunca reescrito em silêncio.
juntar: o que você declara ao cruzar
| Campo | O que significa |
|---|---|
| segunda tabela | A tabela do cruzamento. Sempre do mesmo workspace — os guards do datalake exigem o prefixo do tenant também nela |
| modo | esquerda (mantém todas as suas linhas) ou interna (mantém só as que casam) |
| chaves | O ON, com um ou mais pares: minha coluna = coluna dela |
| colunas | A lista permitida do lado direito, na ordem de saída. Ausente = todas as colunas dela menos as chaves do ON |
| cardinalidade esperada | 1-1, N-1, 1-N ou N-N, do ponto de vista das suas linhas |
Quando uma coluna do lado direito colide com uma chave sua, ela sai prefixada t2_ — regra estática, porque o SQL não pode depender do schema do momento.
A prevenção de fan-out, em três regras
A cardinalidade é declarada por você; a validação é estática e fail-closed:
1-1eN-1passam sem aviso: o lado direito não multiplica suas linhas.1-NeN-Nsão bloqueadas quando o pipeline não agrupa depois, ou quando oagruparseguinte usasoma,mediaoucontagemsobre coluna que não é provadamente do lado direito do cruzamento. Dois casos específicos:contagemsem coluna conta linhas — e linhas multiplicadas inflam a contagem. Para contar registros únicos, usecontagem_distinta.- Se o cruzamento não listou as colunas do lado direito, nenhuma coluna é provadamente direita (é o fail-closed): liste as colunas ou aprove explicitamente.
- Aprovação explícita libera, com aviso — nunca em silêncio.
A mensagem que o produto mostra é literal, e vale ler com calma: "este cruzamento pode multiplicar suas linhas (1-N): uma venda com 3 itens viraria 3 linhas e a soma de receita triplicaria. … Se é isso que você quer, marque 'aprovar multiplicação'."
E um lembrete honesto: a validação é estática. Ela confere o que você declarou, não o que a sua tabela tem hoje. A verificação empírica (contar linhas antes e depois) é trabalho da execução paralela de conferência — o que nos leva à aula 11. Declarar N-1 numa relação que na verdade é 1-N passa pela validação e dá número errado: a conferência contra a Silver é obrigatória.
Exemplo: a Comércio Aurora
Maria quer gold.vendas_mensal_filial (receita e pedidos por mês e filial):
1) datas: data_pedido → truncar_mes (cria o mês)
2) juntar: filiais, modo esquerda,
chaves: filial_id = id,
colunas: [nome, uf, regiao],
cardinalidade esperada: N-1 (muitas vendas, uma filial)
3) agrupar: chaves [mes, nome, uf],
agregações: soma(valor) → receita,
contagem_distinta(pedido_id) → pedidosO cruzamento é N-1: passa sem aviso. Se ela acrescentasse itens_venda (várias linhas por venda) com cardinalidade 1-N e mantivesse soma(valor) sobre a coluna de vendas, o passo seria bloqueado com a mensagem da venda de 3 itens. A saída correta nesse caso é agrupar antes de cruzar, ou somar a coluna do lado direito (soma(item_valor)), ou aprovar a multiplicação sabendo o que está fazendo.
Depois de rodar, Maria confere: SOMA(receita) de gold.vendas_mensal_filial tem de dar exatamente a soma de valor na Silver de vendas. Se não der, é fan-out — não é "arredondamento".
Erros comuns
| Sintoma | Causa provável | O que fazer |
|---|---|---|
| A receita do Gold é múltipla da Silver | Fan-out: cruzamento com várias linhas por venda | Agrupe antes de cruzar, ou some a coluna do lado direito |
O passo juntar foi bloqueado | 1-N/N-N sem agrupamento seguro depois | Reveja a cardinalidade real; liste as colunas do lado direito |
| "não dá para garantir que ela vem do lado cruzado" | O cruzamento não listou as colunas (fail-closed) | Informe a lista de colunas do lado direito |
| A contagem de pedidos ficou inflada | contagem sem coluna conta linhas | Use contagem_distinta sobre a chave do pedido |
Apareceu uma coluna t2_filial_id | Colisão de nome com uma chave sua | É a regra de prefixo; renomeie na saída se incomodar |
| O mart ficou com uma linha só | agrupar sem chaves = agregação global | Informe as chaves — ou era isso que você queria (mart de KPI) |
Declarei N-1 e o número continua errado | A relação real é 1-N | A validação é estática: confira o total contra a Silver |
O que é Preview aqui
O agrupamento, os joins e a prevenção de fan-out consciente de grão são provados por teste determinístico (C04.5 = GA-candidato). A verificação empírica de cardinalidade e a materialização real em BigQuery dependem de execução em nuvem — Preview. Nada aqui é "GA".
Faça você mesmo#
No workspace de treino Aurora Varejo, construindo gold.vendas_mensal_filial sobre a Silver de vendas e filiais.
- Em
/sources, etapa Transformações, crie a tabela Gold a partir da Silver devendas. - Acrescente
datas: data_pedido → truncar_mespara criar a coluna de mês. - Acrescente juntar com
filiais: modo esquerda, chavefilial_id = id, colunas[nome, uf, regiao], cardinalidade esperada N-1. Confirme que não aparece aviso de multiplicação. - Acrescente agrupar: chaves
[mes, nome, uf]; agregaçõessoma(valor)com nomereceitaecontagem_distinta(pedido_id)com nomepedidos. - Agora provoque o bloqueio: mude a cardinalidade do cruzamento para 1-N e tente salvar. Leia a mensagem inteira e anote o motivo.
- Troque
contagem_distinta(pedido_id)porcontagemsem coluna (ainda em 1-N) e leia a segunda mensagem — ela é diferente. - Volte para N-1 com
contagem_distinta, publique e rode. - No Console de dados, compare
SOMA(receita)do mart Gold com a soma devalorna Silver devendas. Os números têm de ser iguais.
Você terminou quando gold.vendas_mensal_filial existe com receita e pedidos por mês e filial, o total do Gold bate exatamente com a Silver, e você provocou e leu duas mensagens diferentes de prevenção de fan-out.
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#
C04.5 — o selo exibido na aula é sempre o estado mais conservador entre as capacidades citadas; nada aqui é "GA".