Toolvore

CSV Join

Match two CSV tables by exact text keys, review unmatched records and download the joined data locally.

This tool runs entirely in your browser. Your data is never uploaded, never stored, and never leaves your device.

CSV Join connects two tables by an exact text key, supports inner, left and full joins, and exports both source columns plus unmatched-row reports without uploading the files.

How to use it

  1. 1Load or paste two CSV tables, select each delimiter and read the columns.
  2. 2Choose one key per table, a join mode and whether empty keys may match.
  3. 3Review matching pairs and unmatched counts, then download the joined CSV and diagnostics.

Example

Input
Left id,name: 001,Mira; 002,Leo Right id,order: 001,A10; 001,A11 Left join on id
Output
001,Mira joins A10 and A11 as two rows. 002,Leo remains as one left_only row.

Duplicate keys produce every matching pair; neither source value is overwritten.

What happens to your data

Both tables are parsed and joined in this browser. Inputs are not uploaded by this workflow; joined and unmatched CSV files are generated locally. Clearing or editing invalidates the prior result.

Last updated October 2026

Join two CSV files by a shared identifier without uploading either table. Choose the key independently on each side, keep matching pairs only or preserve unmatched records, and download the joined table plus separate unmatched-left and unmatched-right reports. This is a horizontal join: it connects columns from related records rather than appending one file below another.

Use a product SKU to connect inventory with a supplier export, or a customer ID to attach order records. Every original column remains in the result, including both keys, so you can inspect which source supplied a value. The tool never silently overwrites a left-hand value with a right-hand value.

How it works

Load or paste two UTF-8 tables and choose each source delimiter: comma, semicolon or tab. Read both tables, select their key columns, choose the join type and review the result. A unique, nonempty header is required in each source; header names may differ between the two files. Quoted delimiters, doubled quotes and multiline fields are parsed as CSV, not split on physical lines. Malformed quoting or unequal field counts stops processing.

Matching compares exact strings. The identifiers 001, 1 and 1.0 remain different, and case and spaces matter. Empty-string keys do not match by default: an empty ID is usually missing information, not evidence that two records belong together. You can explicitly allow empty keys to match. A space-only key is not an empty string; it remains ordinary exact text.

Inner join includes matching pairs only. Left join also retains every unmatched left record. Full join includes those records and appends every unmatched right record. Missing-side fields are empty strings, and join_status labels each output record as matched, left_only or right_only. Headers are always prefixed left. or right., so equal names on the two sides cannot overwrite each other. The status distinguishes inserted empty fields from genuine blanks in a matched record.

Duplicate keys are not deduplicated. Two left rows and three right rows with the same key produce six matching pairs. Matches retain left-row order and, within each left row, right-row order. Unmatched-right records appear last in full mode, in right-source order. The unmatched reports contain original source columns and every unmatched source row, even if the selected join excludes them. A report with no unmatched rows is header-only. Duplicate-key counts count distinct eligible key values repeated within each source, not output pairs.

Each input is limited to 2 MiB, 10,000 records including its header, 200 fields and 200,000 cells. The joined result may contain at most 20,000 data rows, 200 columns including join_status, 200,000 cells including its header and 10 MiB of encoded CSV. Both expanded row count and exact output byte budget are checked before joined rows are constructed. Reduce repeated keys or large fields if a small source would multiply into an oversized result. This is not a streaming join for multi-gigabyte files.

All parsing, matching and downloads run in this browser. Changing either input or its delimiter clears parsed columns and previous downloads; changing a join or export setting clears the result. Downloads use your selected output delimiter, UTF-8, CRLF record endings and no BOM. Original field text is preserved unless you enable apostrophe-prefix protection for formula-like cells. That option affects exports, not key matching, and also affects negative numbers. Spreadsheet behavior varies; import identifier columns as text. The preview shows at most eight rows and six columns with long text abbreviated.

Worked example: Attach two orders while retaining an unmatched customer

Input
Left: id,name 001,Mira 002,Leo Right: customer_id,order 001,A10 001,A11 004,A12 Keys: id / customer_id; left join; empty matching off
Result
join_status,left.id,left.name,right.customer_id,right.order matched,001,Mira,001,A10 matched,001,Mira,001,A11 left_only,002,Leo,"",""

Mira appears twice because two orders match. Leo remains with missing right fields. The separate unmatched-right report contains customer 004.

Common use cases

  • Connecting product and supplier tables by an exact SKU
  • Attaching multiple orders to customer records without dropping duplicates
  • Finding IDs missing from either of two exports
  • Auditing a full join while preserving both source columns

Frequently asked questions

Is joining CSV files the same as merging them?+

Not necessarily. This tool adds columns by matching a key. CSV Merge appends records vertically by header name. Use join for related tables such as customers and orders; use merge for successive exports with the same kind of rows.

Why did joining create more rows than either file?+

Duplicate keys create every matching pair. Three rows on one side and four on the other produce twelve pairs. Review the repeated-key counts or use CSV Deduplicate first if your intended key must be unique. The tool does not choose an arbitrary winner.

Can I join on different column names or different delimiters?+

Yes. Select each key independently after reading the tables, and choose comma, semicolon or tab for each input. Output delimiter is a separate setting. Composite multi-column keys and fuzzy matching are not supported.

Will leading zeros or large identifiers be lost?+

No numeric conversion is used for matching or export. The key 9007199254740993 remains text, as does 001. Your spreadsheet can still infer types when opening the result; import those columns as text.

How do I distinguish a missing match from an empty source cell?+

Check join_status. A matched row can contain genuine empty fields. A left_only or right_only row has blank placeholders for the absent side, while both source key columns remain available for inspection.

Does the unmatched report depend on the selected join type?+

No. Both reports describe source rows that found no partner under the chosen key and empty-key rule. An inner join excludes them from the main result but still offers them as separate downloads.