Skip to main content
This gem runs in .

Overview

Use the Join gem to combine related data from two or more datasets. Common use cases include:
  • adding customer details to order records
  • combining user activity with account information
  • enriching datasets with lookup tables
  • matching records between systems
The Join gem matches rows using one or more join conditions, such as matching customer IDs or order numbers. By default, the Join gem provides a guided interface for choosing a join type, defining match conditions, and selecting output columns. If you need more than two input datasets or a condition that Simple mode can’t represent, you can switch to Advanced mode to edit the underlying SQL configuration directly.

Modes

The Join gem supports two editing modes:

Simple mode

Simple mode organizes the Join gem into three parts. The dialog also shows a Where rows go panel that explains which output port each row of your data lands on for the selected join type. See Output ports in Simple mode.

Match rows on

Each row compares one column from the first input to one column from the second input using an operator: Multiple rows are combined with AND. If your join needs OR logic, a function call, or any comparison Simple mode can’t show as a row, the gem falls back to Advanced mode — see Complex joins.

Output columns

Pick any column from either input to include in the result. If you don’t rename a column, Prophecy uses the column name as the output name automatically. Semi and anti joins only offer columns from the first input. A semi join keeps rows from the first input that have a match in the second, and an anti join keeps rows from the first input that don’t. Neither one adds columns from the second input to the result.

How to choose a join type

Simple mode’s join-type dropdown offers Inner, Left Outer, and Right Outer Join. Full Outer, Cross, Natural, and Semi/Anti joins are only available in Advanced mode.

Complex joins

Simple mode can represent a join when all of the following are true:
  • Exactly two input datasets are connected.
  • There’s exactly one join condition connecting them.
  • The join type is Inner, Left Outer, or Right Outer (or another type already configured in Advanced mode that Simple mode recognizes).
  • The condition is one or more column comparisons combined with AND (no OR, no functions).
  • Every output column is a plain column pick, not a calculated expression like concat(a, b).
If any of these aren’t true, Simple mode shows a message that the configuration is too complex to edit there. From this message you have two options:
  • Switch to Advanced Mode lets you edit the existing configuration directly.
  • Reset and use Default Mode clears the match conditions and output columns so you can start over with a simple inner join.
Reset and use Default Mode permanently removes the existing match conditions and output columns.
If the gem has more than two input datasets, only Switch to Advanced Mode is available — reducing the join to two inputs isn’t something Reset can do for you.

Common join examples

Input and Output

Adding a third input, or opening a gem that already has one, moves the Join gem to Advanced mode — Simple mode only represents two-input joins.

Output ports in Simple mode

In Simple mode the Join gem always has three output ports, in this order: Which reject ports actually carry rows depends on the join type: A Left Outer join, for example, keeps every row from the first input in the matched output, so out0 never has anything to emit — but a right-side row with no match is dropped from the joined result, and shows up on out2 instead of disappearing silently. Connect a reject port downstream if you want to inspect or route unmatched rows rather than losing them.

Output port in Advanced mode

Advanced mode configuration

Advanced mode exposes the underlying join configuration directly, instead of the guided Simple mode cards.

Join conditions

You can add one or more join conditions to the gem depending on the number of input tables added. Rows are matched using shared values, such as customer IDs, order IDs, or email addresses.
If you want to use a type of join that is available in your SQL warehouse, you can type the name of that join directly in Prophecy.

Expressions

Example

Assume you have two tables: orders and customers. You want the orders table to include customer information, so you need to join the tables based on customer ID. You only want to preserve records in the output that have a match. To do so:
  1. Connect orders to in0 and customers to in1.
  2. Choose Inner Join as the join type.
  3. If using a visual expression, use the following join condition: in0.CustomerID equals in1.customer_id
  4. If using the code expression, use the following SQL join condition: in0.CustomerID = in1.customer_id
  5. Leave the Expressions tile empty.
  6. Save and run the gem.

Common issues

Duplicate rows after joining

Duplicate rows can occur when multiple rows in one table match the same row in another table. Verify that:
  • the join keys are unique when expected
  • the correct join type is selected
  • duplicate records do not exist in the input datasets

Missing records in the output

Rows may be excluded depending on the selected join type. For example:
  • Inner Join keeps only matching rows
  • Left Join keeps all rows from the left table
  • Full Outer Join keeps all rows from both tables
In Simple mode, check the reject ports (out0 / out2) — rows that don’t appear in the matched output often show up there instead of being silently dropped. See Output ports in Simple mode.

Null values in joined columns

Rows with NULL join keys may not match other rows.

Ambiguous column names

If both datasets contain columns with the same name, rename or qualify columns to avoid ambiguity.

Join types

Suppose there are two tables, Employees and Departments, with the following contents:

Employees

Departments

INNER JOIN

Inner Join will return columns from both the tables and only the matching records as long as the condition is satisfied. For example, if the Join condition provided was employees.department_id = departments.department_id, the sample query would be:

LEFT JOIN / LEFT OUTER JOIN

Left Join (or Left Outer join) will return columns from both the tables and match records with records from the left table. The result-set will contain null for the rows for which there is no matching row on the right side. For example, if the Join condition provided was employees.department_id = departments.department_id, the sample query would be:

RIGHT JOIN / RIGHT OUTER JOIN

Right Join (or Right Outer Join) returns matching rows from both tables and preserves all rows from the right table. Rows from the right table that do not have a match in the left table will contain NULL values for the left table columns. For example, if the join condition is employees.department_id = departments.department_id, the sample query would be:

FULL JOIN / FULL OUTER JOIN

Full Outer Join will return columns from both the tables and matching records with records from the left table and records from the right table. The result-set will contain NULL values for the rows for which there is no matching. For example, if the Join condition provided was employees.department_id = departments.department_id, the sample query would be:

CROSS JOIN

Returns the Cartesian product of two datasets. It combines all rows from both tables. Cross Join will not have any Join conditions specified. For example, the sample query would be:

LEFT SEMI JOIN

A semi join returns rows from the left table that have at least one matching row in the right table — but only the left table’s columns come through. Unlike an Inner Join, a semi join never duplicates a left row when it has more than one match on the right. For example, if the join condition provided was employees.department_id = departments.department_id, the sample query would be:

LEFT ANTI JOIN

An anti join returns rows from the left table that have no matching row in the right table — the inverse of a semi join. Only the left table’s columns come through. For example, if the join condition provided was employees.department_id = departments.department_id, the sample query would be:

NATURAL INNER JOIN

A natural join (or Natural Inner Join) is identical to an explicit Inner Join but it automatically joins columns with the same names in both tables. Natural Join will not have any join conditions specified. For example, the sample query would be:

NATURAL LEFT OUTER JOIN

A natural Left Outer join (or Natural Left Join) is identical to an explicit Left Outer Join but it automatically joins columns with the same names in both tables. Natural Left Outer Join will not have any join conditions specified. For example, the sample query would be:

NATURAL RIGHT OUTER JOIN

A natural Left Right join (or Natural Right Join) is identical to an explicit Right Outer Join but it automatically joins columns with the same names in both tables. Natural Right Outer Join will not have any join conditions specified. For example, the sample query would be:

NATURAL FULL OUTER JOIN

A natural Full Outer join (or Natural Full Join) is identical to an explicit Full Outer Join but it automatically joins columns with the same names in both tables. Natural Full Outer Join will not have any join conditions specified. For example, the sample query would be:

Similar tools and concepts

The Join gem combines related data from multiple datasets using shared column values. You may recognize similar behavior from:
  • SQL JOIN operations
  • the Alteryx Join tool
  • PySpark join()
  • Pandas merge()