Set Operations on Two TSV Files
Two lists and one question: what's in both, what's only in one. This is the tool for "which of these customers already exist", "what did last month's export have that this month's doesn't", "merge these two lists without duplicates". Compare whole rows, or name a key column and compare on that alone — which is what you need when the other columns differ but the identity doesn't.
How to use
- Paste or drop both files. If they have header rows, leave no header row unchecked — A's header is used for the output and B's is ignored.
- Pick the operation. The status line always reports all three counts — in both, only in A, only in B — no matter which one you chose, so a single run answers the whole question.
- Leave compare on blank to match whole rows, or name one or more columns to match on identity alone.
- Turn on trim and ignore case if the two files came from different systems. They almost always disagree about both.
Whole rows versus key columns
With compare on blank, two rows are the same only if every cell matches. That's the right default for "did this file change", and it means a row that differs by one character counts as being in neither intersection nor either difference cleanly — it appears in both "only in A" and "only in B". That is not a bug: by whole-row comparison, they genuinely are different rows.
Name a key column and the comparison uses only that. Now a customer whose address changed is "in both", and the output keeps A's version of the row. This is the mode you want for reconciling exports; use TSV diff instead when you want to see what changed rather than which side a row is on.
Which operation answers which question
A ∩ B — already exists, already processed, overlap between two audiences. A − B — new since last time, still to do, unsubscribed. B − A — the same question from the other side; useful when B is the newer file and you want additions rather than removals. A ∪ B — one combined list, each row once. A + B — plain concatenation with duplicates left in, for when you want the counts preserved; merge files is the fuller version of this with column alignment. A △ B — everything that isn't in both, which is the quickest way to see the full extent of a divergence.
Deduplication applies within the output of every operation except stack, so if A itself contains the same row twice, the union has it once. If you want the duplicate counts instead, run value counts on the key column first.
FAQ
Do the two files need the same columns?
For whole-row comparison, yes — different column orders produce different rows and nothing will match. For key-column comparison the columns are resolved by name on each side independently, so the files only have to agree about the key. Output rows keep whatever shape they had in their source file.
Is this the same as a join?
No. A set operation returns rows, with the same columns they came in with. A join returns rows widened with the other file's columns. If you want to know which rows overlap, use this; if you want to attach B's data to A's rows, use the join.
Why does my intersection come back empty?
Almost always invisible whitespace or a case difference — turn on both checkboxes. After that, the usual culprits are a UTF-8 BOM on one file only (handled automatically here), CRLF versus LF (also handled), and leading zeros stripped by Excel on one side. The status line's "only in A / only in B" counts tell you immediately whether the keys are simply disjoint.
How large can the files be?
Both files and the result are held in memory at once, and a key index is built for each side. A few hundred thousand rows per file is comfortable in a modern browser; past a million, use sort and comm on the command line, or load both into SQLite.
Privacy
100% client-side. Neither file is uploaded. See the privacy policy.