# Join more than two tables

Join / keyed

A variant of [Join tables on a key](https://meridian.online/operations/join-tables-on-a-key).

Join three or more tables on their shared keys in one step.

Page: <https://meridian.online/operations/join-tables-on-a-key/join-more-than-two-tables>

## Status

Runs as a SQL step.

arcform carries it as a `sql:` step today.

## The DuckDB step

join four tables on a shared key in one statement

```sql
CREATE TEMP TABLE a AS SELECT * FROM (VALUES ('a1', 'a'), ('a2', NULL), ('a3', 'b'), ('a4', 'c')) t(av, k);
CREATE TEMP TABLE b AS SELECT * FROM (VALUES ('a', 'b1'), ('a', 'b2'), (NULL, 'b3'), ('b', 'b4')) t(k, bv);
CREATE TEMP TABLE c AS SELECT * FROM (VALUES ('a', 'c1'), ('a', 'c2'), ('b', 'c3'), (NULL, 'c4'), ('c', 'c5')) t(k, cv);
CREATE TEMP TABLE d AS SELECT * FROM (VALUES ('a', 'd1'), ('c', 'd2'), ('d', 'd3')) t(k, dv);
-- key a is in all four tables (1 x 2 x 2 x 1 = 4 rows); b is missing from d and c from b, so each drops out at its missing table; a NULL key matches nothing
CREATE TEMP TABLE result AS
SELECT a.k, a.av, b.bv, c.cv, d.dv FROM a JOIN b ON a.k = b.k JOIN c ON a.k = c.k JOIN d ON a.k = d.k;
SELECT * FROM result ORDER BY ALL;
SELECT CASE WHEN ((SELECT count(*) = 4 AND count(*) FILTER (WHERE k = 'a') = 4
      AND count(*) FILTER (WHERE k IN ('b', 'c') OR k IS NULL) = 0
      AND list(bv || cv ORDER BY bv, cv) FILTER (WHERE k = 'a') = ['b1c1', 'b1c2', 'b2c1', 'b2c2'] FROM result)) THEN 'as expected' ELSE error('four tables joined on one key should give 4 rows for the key found twice in two tables, and none for the keys b and c, each missing from one table, or for a NULL key') END AS verdict;
```

The statement builds its own data.

It needs nothing installed beyond DuckDB itself.

## What other tools call it

Meridian's classification; an independent blind rating agreed on 95.7% of 324 rows (variant, version 3).

- Alteryx Designer: [`Join Multiple`](https://help.alteryx.com/current/en/designer/tools/join/join-multiple-tool.html) (read 2026-09-27)
- Apache Hop: [`Multiway Merge Join`](https://hop.apache.org/manual/latest/pipeline/transforms/multimerge.html) (read 2026-09-27)
- Ibis: [`JoinChain`](https://github.com/ibis-project/ibis/blob/05d2b293344e86cb41c1a426071734f7e270335a/ibis/expr/operations/relations.py) (read 2026-09-27)
- Pentaho Data Integration: [`Multiway Merge Join`](https://docs.pentaho.com/pdia-data-integration/9.3-data-integration/pdi-transformation-steps-reference-overview) (read 2026-09-27)
- Polars: [`align_frames`](https://docs.pola.rs/api/python/stable/reference/functions.html) (read 2026-09-27)
- VisiData: [`join-sheets-all`](https://github.com/saulpw/visidata/blob/7609212ec2febafa9caba7183cbebfaf49627909/visidata/features/join.py#L409) (read 2026-09-23)
