# CSV Join

Join two CSV files on a key column, SQL-style — inner, left, right, or full outer. Different key names, custom delimiter, case control. In your browser, no upload.

## Run it

- **CLI:** `gizza tool csv-join "id,name
1,Alice
2,Bob
3,Carol" 'right=id,city
2,Berlin
3,Cairo
4,Delhi' 'left_key=id'`
- **Web:** https://gizza.ai/tools/csv-join/
- **Agents:** machine-readable descriptor (parameters JSON Schema) at https://gizza.ai/tools/csv-join/tool.json

## Inputs

- `left` — Left CSV _(field)_
- `right` — Right CSV _(field)_
- `left_key` — Left key column (header name or 1-based index) _(field)_
- `right_key` — Right key column (blank = same as left) _(field)_
- `join_type` — Join type _(field)_
- `delimiter` — Delimiter (, tab ; |) _(field)_
- `case_sensitive` — Case-sensitive key match _(field)_

## Output

- Joined CSV (text)

## Query parameters

Open the tool pre-filled and auto-run via URL:

- `left` — Left CSV
- `right` — Right CSV
- `left_key` — Left key column (header name or 1-based index)
- `right_key` — Right key column (blank = same as left)
- `join_type` — Join type
- `delimiter` — Delimiter (, tab ; |)
- `case_sensitive` — Case-sensitive key match

Example: `https://gizza.ai/tools/csv-join/?left=id%2Cname%0A1%2CAlice%0A2%2CBob%0A3%2CCarol&right=id%2Ccity%0A2%2CBerlin%0A3%2CCairo%0A4%2CDelhi&left_key=id&right_key=id&join_type=inner&delimiter=%2C&case_sensitive=true`

---

## About this tool

CSV Join merges two CSV files into one by matching rows on a **key column** — the
same idea as a SQL `JOIN` or a spreadsheet `VLOOKUP`, but on whole tables at once.
Paste your left and right CSVs, name the key column on each side, pick a join type,
and get a single combined table back.

Four join types cover the usual cases:

- **Inner** — keep only rows whose key appears in **both** files.
- **Left** — keep every left row; fill blank cells where the right file has no match.
- **Right** — keep every right row; fill blanks on the left side.
- **Outer** (full outer) — keep **every** row from both files, blanks where a side is missing.

The key is matched on **values**, not column names, so the two key columns can be
named differently (`user_id` on the left, `uid` on the right). Reference a key by
its header name or by 1-based position. The output keeps the full left header, then
appends every non-key column from the right file; if a right column name collides
with a left one it gets a `_right` suffix so nothing is silently overwritten.

Everything runs locally in your browser — your data is never uploaded.

## FAQ

<details>
<summary>What if the two files use different names for the key column?</summary>

That's fine — the join matches on the **values** in the key columns, not their
names. Set the left key (e.g. `user_id`) and the right key (e.g. `uid`)
independently. Leave the right key blank to reuse the left key's name or index.

</details>

<details>
<summary>What's the difference between inner, left, right, and outer joins?</summary>

**Inner** keeps only keys present in both files. **Left** keeps all left rows
(blank right cells when unmatched), **right** keeps all right rows, and **outer**
keeps every row from both sides, padding the missing side with blanks. Inner is the
default.

</details>

<details>
<summary>What happens when both files have a column with the same name?</summary>

The output keeps the full left header first, then appends the right file's non-key
columns. If a right column's name already exists in the output, it's suffixed with
`_right` (e.g. `name` and `name_right`) so both values are preserved.

</details>

<details>
<summary>What if a key value appears more than once?</summary>

Duplicate keys produce a Cartesian product for that key — one output row per
matching left×right pair — exactly like a SQL join. Two left rows and three right
rows sharing a key yield six joined rows.

</details>

<details>
<summary>Can I join on a column by position instead of by name?</summary>

Yes. Enter a 1-based column index (e.g. `1` for the first column) instead of a
header name for either key. This is handy when your headers are awkward or absent.

</details>

<details>
<summary>Does the delimiter have to be a comma?</summary>

No. Set the delimiter to `,`, `tab`, `;`/`semicolon`, `|`/`pipe`, or any single
character. The same delimiter is used to parse both inputs and to write the result.

</details>

## Related tools

- [Avro to JSON Converter](https://gizza.ai/tools/avro-to-json/): Decode Apache Avro Object Container Files (.avro / OCF) to JSON, NDJSON, or the embedded schema — no .avsc needed, free and private in your browser.
- [Bencode decoder](https://gizza.ai/tools/bencode-decoder/): Decode bencode (the BitTorrent / .torrent serialization format) into readable JSON, and re-encode JSON back into canonical bencode — in your browser. Nothing is uploaded.
- [Change CSV Delimiter](https://gizza.ai/tools/csv-change-delimiter/): Re-save CSV or delimited data with a different separator (comma, tab, semicolon, pipe) with correct requoting — in your browser. Free, private, no upload.
- [CSV Cleaner](https://gizza.ai/tools/csv-cleaner/): Clean a messy CSV in your browser: trim whitespace, remove duplicate rows, drop empty rows, fill blanks, and normalize delimiters. No upload, free.
- [CSV Dedupe](https://gizza.ai/tools/csv-dedupe/): Remove duplicate rows from a CSV, keeping the first — optionally keyed on chosen columns. Runs in your browser, nothing is uploaded, free.
