JoinTransformer
Visão geral
Converte nós Join do Tableau em instruções SQL JOIN. Combina dois conjuntos de dados de entrada com base nas condições de junção, com suporte a múltiplos tipos de junção (INNER, LEFT, RIGHT, FULL e ANTI).
Tipo de nó: .v1.SimpleJoin / .v2018_2_3.SuperJoin
Saída: SQL SELECT com JOIN
Recursos
- Tipos de junção: INNER, LEFT, RIGHT, FULL, LEFT ANTI, RIGHT ANTI
- Múltiplas condições de junção (lógica AND)
- Comparações de igualdade (==)
- Tratamento de nomes de colunas duplicados com sufixos
- Aliases de tabelas para maior clareza
Exemplo de nó Tableau
Exemplo 1: junção interna em múltiplas colunas
Entrada (formato Tableau)
{
"id": "7bf017f8-2d70-411f-8af2-a831301b1c66",
"name": "Join Sales by Period",
"node_type": ".v2018_2_3.SuperJoin",
"base_type": "superNode",
"actionNode": {
"nodeType": ".v1.SimpleJoin",
"joinType": "inner",
"conditions": [
{
"comparator": "==",
"leftExpression": "[Year]",
"rightExpression": "[Year]"
},
{
"comparator": "==",
"leftExpression": "[Month]",
"rightExpression": "[Month]"
}
]
}
}
Esquemas de entrada
Entrada esquerda (dados de vendas):
[
{"name": "year", "type": "integer"},
{"name": "month", "type": "integer"},
{"name": "region", "type": "string"},
{"name": "sales_amount", "type": "real"},
{"name": "customer_name", "type": "string"}
]
Entrada direita (dados de metas):
[
{"name": "year", "type": "integer"},
{"name": "month", "type": "integer"},
{"name": "target_amount", "type": "real"}
]
SQL gerado
SELECT
a.region,
a.sales_amount,
a.customer_name,
a.month,
a.year,
b.target_amount,
b.ano AS year_1,
b.mes AS month_1
FROM sales_data_V0S12 AS a
INNER JOIN targets_V0S15 AS b
ON a.year = b.year AND a.month = b.month
Esquema de saída
{
"region": "string",
"sales_amount": "real",
"customer_name": "string",
"month": "integer",
"year": "integer",
"target_amount": "real",
"year_1": "integer",
"month_1": "integer"
}
Exemplo 2: junção à esquerda (manter todas as linhas da esquerda)
Entrada (formato Tableau)
{
"id": "8c9d0e1f-2a3b-4c5d-6e7f-8a9b0c1d2e3f",
"name": "Join Customers with Orders",
"node_type": ".v1.SimpleJoin",
"actionNode": {
"joinType": "left",
"conditions": [
{
"comparator": "==",
"leftExpression": "[Customer ID]",
"rightExpression": "[Customer ID]"
}
]
}
}
SQL gerado
SELECT
a.customer_id,
a.customer_name,
a.email,
b.order_id,
b.order_date,
b.order_amount,
b.customer_id AS customer_id_1
FROM customers_V0S5 AS a
LEFT JOIN orders_V0S8 AS b
ON a.customer_id = b.customer_id
Exemplo 3: junção à direita
Entrada (formato Tableau)
{
"id": "9d0e1f2a-3b4c-5d6e-7f8a-9b0c1d2e3f4a",
"name": "Right Join Products",
"node_type": ".v1.SimpleJoin",
"actionNode": {
"joinType": "right",
"conditions": [
{
"comparator": "==",
"leftExpression": "[Product Code]",
"rightExpression": "[Product Code]"
}
]
}
}
SQL gerado
SELECT
a.product_code,
a.sales_amount,
b.product_code AS product_code_1,
b.product_name,
b.category
FROM sales_V0S3 AS a
RIGHT JOIN products_V0S7 AS b
ON a.product_code = b.product_code
Exemplo 4: junção externa completa
Entrada (formato Tableau)
{
"id": "0e1f2a3b-4c5d-6e7f-8a9b-0c1d2e3f4a5b",
"name": "Full Join Transactions",
"node_type": ".v1.SimpleJoin",
"actionNode": {
"joinType": "full",
"conditions": [
{
"comparator": "==",
"leftExpression": "[Transaction ID]",
"rightExpression": "[Transaction ID]"
}
]
}
}
SQL gerado
SELECT
a.transaction_id,
a.amount,
a.date,
b.transaction_id AS transaction_id_1,
b.reconciled,
b.status
FROM source_a_V0S10 AS a
FULL OUTER JOIN source_b_V0S12 AS b
ON a.transaction_id = b.transaction_id
Exemplo 5: antijunção à esquerda (linhas apenas da esquerda)
Entrada (formato Tableau)
{
"id": "1f2a3b4c-5d6e-7f8a-9b0c-1d2e3f4a5b6c",
"name": "Find Unmatched Customers",
"node_type": ".v1.SimpleJoin",
"actionNode": {
"joinType": "leftanti",
"conditions": [
{
"comparator": "==",
"leftExpression": "[Customer ID]",
"rightExpression": "[Customer ID]"
}
]
}
}
SQL gerado
SELECT
a.customer_id,
a.customer_name,
a.region
FROM all_customers_V0S4 AS a
LEFT ANTI JOIN active_customers_V0S8 AS b
ON a.customer_id = b.customer_id
Exemplo 6: antijunção à direita (linhas apenas da direita)
Entrada (formato Tableau)
{
"id": "2a3b4c5d-6e7f-8a9b-0c1d-2e3f4a5b6c7d",
"name": "Find Orphaned Records",
"node_type": ".v1.SimpleJoin",
"actionNode": {
"joinType": "rightanti",
"conditions": [
{
"comparator": "==",
"leftExpression": "[Order ID]",
"rightExpression": "[Order ID]"
}
]
}
}
SQL gerado
SELECT
b.order_id,
b.status,
b.created_date
FROM orders_V0S6 AS a
RIGHT ANTI JOIN orphaned_orders_V0S9 AS b
ON a.order_id = b.order_id
Exemplo 7: junção com condição única
Entrada (formato Tableau)
{
"id": "3b4c5d6e-7f8a-9b0c-1d2e-3f4a5b6c7d8e",
"name": "Join by Region",
"node_type": ".v1.SimpleJoin",
"actionNode": {
"joinType": "inner",
"conditions": [
{
"comparator": "==",
"leftExpression": "[Region Code]",
"rightExpression": "[Region Code]"
}
]
}
}
SQL gerado
SELECT
a.region_code,
a.sales_amount,
b.region_code AS region_code_1,
b.region_name,
b.manager
FROM sales_V0S2 AS a
INNER JOIN regions_V0S5 AS b
ON a.region_code = b.region_code
Como funciona
1. Identificar o tipo de junção
Lê joinType de actionNode:
{
"joinType": "inner"
}
Tipos suportados:
inner→ INNER JOINleft→ LEFT JOINright→ RIGHT JOINfull→ FULL OUTER JOINleftanti→ LEFT ANTI JOINrightanti→ RIGHT ANTI JOIN
2. Analisar as condições de junção
Extrai o array conditions:
{
"conditions": [
{
"comparator": "==",
"leftExpression": "[Year]",
"rightExpression": "[Year]"
},
{
"comparator": "==",
"leftExpression": "[Month]",
"rightExpression": "[Month]"
}
]
}
3. Converter em cláusula SQL ON
Traduz as condições em SQL:
[Year] == [Year] → a.year = b.year
[Month] == [Month] → a.month = b.month
Múltiplas condições são combinadas com AND:
ON a.year = b.year AND a.month = b.month
4. Tratar nomes de colunas duplicados
Quando ambas as entradas têm os mesmos nomes de colunas:
- Colunas de junção: Aparecem de ambos os lados (com sufixo no lado direito)
- Colunas fora da junção: Se duplicadas, recebem sufixo no lado direito
Exemplo:
Left: year, month, sales_amount
Right: year, month, target_amount
Output:
- year (from left)
- month (from left)
- sales_amount (from left)
- target_amount (from right)
- year_1 (from right, suffixed)
- month_1 (from right, suffixed)
5. Gerar aliases de tabelas
Cria aliases de tabelas para maior clareza:
- Entrada esquerda:
AS a - Entrada direita:
AS b
Todas as referências a colunas recebem o prefixo do alias:
a.year, a.month, b.target_amount
6. Construir a instrução JOIN completa
SELECT
a.column1,
a.column2,
b.column3,
b.column1 AS column1_1 -- duplicate, suffixed
FROM left_input AS a
<JOIN_TYPE> JOIN right_input AS b
ON <join_conditions>
Comparação dos tipos de junção
INNER JOIN
Retorna apenas linhas com correspondências em ambas as tabelas.
Left: 100 rows
Right: 80 rows
Result: 50 rows (only matches)
LEFT JOIN
Retorna todas as linhas da tabela esquerda e NULL para linhas da direita sem correspondência.
Left: 100 rows
Right: 80 rows
Result: 100 rows (all left + matches)
RIGHT JOIN
Retorna todas as linhas da tabela direita e NULL para linhas da esquerda sem correspondência.
Left: 100 rows
Right: 80 rows
Result: 80 rows (all right + matches)
FULL OUTER JOIN
Retorna todas as linhas de ambas as tabelas, com NULL onde não há correspondência.
Left: 100 rows
Right: 80 rows
Result: 130 rows (all rows from both)
LEFT ANTI JOIN
Retorna apenas linhas da tabela esquerda SEM correspondência na tabela direita.
Left: 100 rows
Right: 80 rows
Result: 50 rows (left-only rows)
RIGHT ANTI JOIN
Retorna apenas linhas da tabela direita SEM correspondência na tabela esquerda.
Left: 100 rows
Right: 80 rows
Result: 30 rows (right-only rows)
Múltiplas condições de junção
As condições de junção são combinadas com lógica AND:
{
"conditions": [
{"leftExpression": "[Year]", "rightExpression": "[Year]"},
{"leftExpression": "[Month]", "rightExpression": "[Month]"},
{"leftExpression": "[Region]", "rightExpression": "[Region]"}
]
}
Converte em:
ON a.year = b.year
AND a.month = b.month
AND a.region = b.region
Todas as condições devem ser satisfeitas para haver correspondência.
Padrão de sufixos para colunas duplicadas
Quando existem nomes de colunas duplicados:
Padrão 1: duplicação de coluna de junção
Join on: Customer ID
Left has: customer_id
Right has: customer_id
Output:
- customer_id (from left)
- customer_id_1 (from right)
Padrão 2: duplicação de coluna fora da junção
Left has: amount, date
Right has: amount, date
Output:
- amount (from left)
- date (from left)
- amount_1 (from right)
- date_1 (from right)
Padrão 3: múltiplas duplicatas
Left has: id, name, value
Right has: id, name, status
Output:
- id (from left)
- name (from left)
- value (from left)
- status (from right)
- id_1 (from right)
- name_1 (from right)
O sufixo é incrementado se _1 já existir: _2, _3 etc.
Limitações
- ⚠️ Apenas comparações de igualdade - Apenas o comparador
==é suportado; sem<,>,!=etc. - ⚠️ Apenas duas entradas - Une exatamente dois conjuntos de dados; encadeie múltiplas junções para 3 ou mais tabelas
- ⚠️ Apenas lógica AND - Múltiplas condições são combinadas com AND; lógica OR não é suportada
- ⚠️ Sem expressões complexas - As condições de junção devem ser referências simples a colunas
Boas práticas
Quando usar o transformador Join
- ✅ Combinar conjuntos de dados relacionados - Vendas com metas, clientes com pedidos
- ✅ Enriquecer dados - Adicionar dados de dimensão a tabelas fato
- ✅ Encontrar correspondências/ausências de correspondência - Junções ANTI para verificações de qualidade de dados
Otimização de desempenho de junções
- Filtre antes de unir - Use nós Container anteriores para reduzir a quantidade de linhas
- Una por colunas indexadas - Use colunas de chave primária/estrangeira quando possível
- Escolha o tipo de junção correto - Use INNER JOIN quando possível (mais rápido que OUTER)
- Minimize colunas duplicadas - Selecione apenas as colunas necessárias nos nós anteriores
Encadeamento de múltiplas junções
Para unir 3 ou mais tabelas:
Table A → Join (A + B) → Join (AB + C) → Join (ABC + D)
Cada junção adiciona mais uma tabela ao resultado.
Tratamento de nomes duplicados
Se os sufixos de duplicação forem indesejados:
- Use uma ação RenameColumn anterior para renomear colunas antes da junção
- Use RenameColumn posterior para ajustar os nomes com sufixo após a junção
Transformadores relacionados
- UnionTransformer - Para combinar conjuntos de dados verticalmente (empilhar linhas)
- AggregateTransformer - Para agregar os resultados de junções
- ContainerTransformer - Para filtrar antes ou depois de junções