Skip to main content
v2026.11,610 entries · CC-BY 4.0

Merging Datasets in Stata: 1:1, m:1, and _merge

How Stata’s merge command works by match type (1:1, m:1, 1:m, m:m), how to read the _merge result codes, and the duplicate-master-key and unmatched-observation errors that silently corrupt a join.

Ask about Merging Datasets in Stata: 1:1, m:1, and _merge

Answers are drawn from this guide and the rest of the CASRAI corpus, with a link to every source.

Answers are AI-generated from CASRAI’s own published pages and can be wrong, so check the linked sources before relying on one; your question is logged without personal data — never sold, never used to train a third-party model — to show us what CASRAI is missing, so please do not type personal or confidential details. How we use this

Written and maintained by CASRAI Editorial Board

Last updated

Stata’s merge command joins two datasets on one or more key variables, adding columns rather than rows, and the 1:1/m:1/1:m/m:m declaration you put right after merge is not decoration — it tells Stata what a valid match is supposed to look like, and Stata checks the master and using data against that claim before it joins anything. Get the match type wrong, or ignore what the resulting _merge variable is telling you, and the join can silently duplicate rows, drop observations, or blend data from different units together with no error and no warning banner.

This page covers the four match-type declarations and when each one is correct, how to read every value _merge can take, the assert() and keep() options that turn a silent problem into a command that stops, and the two failure patterns — duplicate keys in the master dataset and unmatched observations — that corrupt a merge without Stata refusing to run it.

The four match types, and why you have to declare one

Full syntax:

merge 1:1 idvar using filename [, options]
merge m:1 idvar using filename [, options]
merge 1:m idvar using filename [, options]
merge m:m idvar using filename [, options]

The declaration describes the relationship between the key variable(s) in the dataset already in memory (the “master”) and the dataset named after using (the “using” data) — specifically, how many times a given key value is allowed to appear on each side:

  • 1:1 — the key is unique in both the master and the using data. Classic case: a roster of participant IDs with demographics, merged against a separate file of one test score per participant. Each id appears exactly once on each side.
  • m:1 — the key can repeat in the master (many observations) but is unique in the using data (one row per key value). Classic case: a long dataset of one row per patient-visit, merged against a lookup table of one row per patient with a fixed birth year or site assignment. Every visit for a given patient picks up the same birth year.
  • 1:m — the mirror image of m:1: the key is unique in the master but repeats in the using data. If you get this backwards relative to which file you loaded first, swap use and merge using, or just declare m:1 instead of 1:m — the two are the same operation from opposite directions.
  • m:m — the key repeats on both sides. Stata will run this, but it does not do what most people expect: it does not produce every combination of matching rows (a full relational many-to-many join). Instead it matches the first master occurrence to the first using occurrence, the second to the second, and so on, in whatever order the data currently sits in — a pairing that depends on sort order and is very rarely the join a researcher actually intends. Treat an m:m declaration as a signal to re-examine the data, not a tool to reach for on purpose; almost every real m:m-shaped problem is actually an m:1 or 1:m merge on the wrong key, or needs a collapse first to make one side unique.

Stata does not take your word for the declared type — it verifies uniqueness on whichever side(s) you claimed were unique and throws an error (variable idvar does not uniquely identify observations in the master data, or the equivalent for the using data) if the claim is false. That check is the single biggest reason to declare the narrowest type that’s actually true, rather than defaulting to m:m to avoid thinking about it: a wrong 1:1 or m:1 declaration fails loudly, right away, before any data has been joined. An m:m declaration never fails this way, because it makes no uniqueness claim to check — which is exactly why it hides the duplicate-key problem covered below instead of catching it.

Reading _merge: what each result code means

Every successful merge creates a variable called _merge (dropped automatically before the next merge, or manually with drop _merge) taking one of three values:

_merge value Label Meaning
1 master only (1) The observation came from the master dataset only — no matching key was found in the using data.
2 using only (2) The observation came from the using dataset only — no matching key was found in the master.
3 matched (3) The key matched on both sides; the merged row combines variables from both.

Run tabulate _merge immediately after every merge, before writing another line of code. This single habit catches most merge problems on the spot: if you expected every master observation to find a match and see any rows coded 1, or expected the using file to be a strict subset and see rows coded 2, you have unmatched observations to investigate before doing anything downstream with the merged dataset — a regression, a table, a recode — that would otherwise run on quietly incomplete data.

assert(): fail loudly instead of checking manually

Rather than merging and then eyeballing the _merge tabulation, assert() states your expectation up front and stops the command with an error if it’s wrong:

merge 1:1 patient_id using labresults.dta, assert(match) keep(match)

assert(match) declares that every observation should match on both sides; if any row comes back coded 1 or 2, Stata raises an error immediately rather than leaving you to discover it later. Other common expectations: assert(match master) for “some using rows may be missing in the master, but every using row must find a home,” or assert(match using) for the reverse. Whatever combination reflects a genuine expectation about your data belongs in assert() — it converts a check you might forget to run into one the command enforces every time.

keep(): controlling which rows survive the merge

By default, merge keeps all observations regardless of match status — matched, master-only, and using-only rows all remain in the dataset, with the unmatched cells for the other file’s variables recorded as missing. keep() restricts what stays:

merge 1:1 patient_id using labresults.dta, keep(match) nogenerate

keeps only rows coded 3, dropping everything that didn’t match on both sides. keep(match master) keeps matched rows plus unmatched master rows (dropping using-only rows), and keep(match using) does the reverse. nogenerate (or gen(none) in older syntax) suppresses the _merge variable entirely once you’ve already used it to decide what to keep and no longer need it in the working dataset. Combining assert() and keep() in the same command is standard practice: assert() confirms the merge behaved as expected, keep() then trims to the rows the analysis actually needs.

Duplicate master keys: the error that only fires on 1:1 and 1:m

The most common cause of a merge silently going wrong is a key variable that isn’t actually unique where a declaration claims it is. If patient_id has been entered twice for one participant — a data-entry duplicate, an unresolved re-enrollment, a trailing whitespace difference that Stata treats as distinct — a 1:1 or m:1 declaration (which both claim uniqueness in the using data) will catch it and error out. But an m:1 or m:m declaration on the master side does not check master-side uniqueness at all, because it doesn’t claim uniqueness there in the first place; a duplicated master key under one of those declarations merges quietly, attaching the same using-file value to both duplicate rows without complaint. The fix is not a merge option — it’s checking key uniqueness before you merge: duplicates report idvar or isid idvar on each file first, so you know which declaration is actually true rather than guessing and hoping the error catches it.

Unmatched observations: what they mean, and why “drop and move on” is a decision, not a default

Unmatched rows (_merge coded 1 or 2) are not automatically an error — they can be entirely expected, such as a using file that legitimately covers only a subset of the master population. The mistake is treating them as automatically fine without checking why they’re unmatched. Common real causes worth ruling out before accepting the count: a key variable stored as string in one file and numeric in the other (Stata will not match them, and gives no warning that the types differ), inconsistent leading zeros or capitalization in an ID field, a date-formatted key that looks identical when browsed but differs at the underlying numeric-storage level, or genuinely different populations that were never expected to match one-to-one in the first place. browse if _merge == 1 (or == 2) before dropping anything, so the unmatched cases are a confirmed, understood set rather than an assumption.

merge vs. append

merge and append solve opposite problems and Stata enforces neither choice for you — both run without error even when the result is meaningless for the analysis. If two files describe the same kind of record repeated — three regional survey files with identical variables, one file per region — that’s append: more rows, same columns. If two files describe different facts about the same units — participant demographics in one file, test scores keyed to the same participant IDs in another — that’s merge: same rows, more columns. See the append command in Stata for the append side of that decision in full.

Frequently asked questions

What does _merge == 3 mean in Stata?

It means that observation’s key matched on both the master and using side, and the merged row combines variables from both datasets. It’s the result code you generally want for every row in a clean 1:1 or m:1 merge with no expected gaps.

How do I merge on more than one variable in Stata?

List all the key variables after the match type: merge 1:1 site_id year using filename matches on the combination of site_id and year together, not on either one alone. Every key variable listed must exist, with matching storage types, in both datasets.

Why does Stata say a variable does not uniquely identify observations?

This error means the declared match type claimed uniqueness on a side of the merge where the key actually repeats — e.g. a 1:1 merge where patient_id appears twice for the same patient in one of the two files. Run duplicates report on the key variable in that dataset to find and resolve the duplicates (or correct the match-type declaration if the repetition is legitimate) before merging.

Should I use m:m merge in Stata?

Almost never on purpose. m:m does not produce a full combinatorial join of every matching pair — it pairs observations positionally, in whatever order they currently sit in, which depends on sort order and rarely matches what a researcher actually wants. An apparent m:m situation is usually really an m:1 or 1:m merge on the wrong key, or a case that needs a collapse on one side first to make its key unique.

What’s the difference between merge and append in Stata?

merge joins two datasets on a shared key, adding columns for the same observations. append stacks two datasets with the same variables, adding rows. See the section above and the append command in Stata for the full comparison.

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →

Regulatory Radar

Stop finding out after the fact

$29/month, cancel anytime. Daily digest updates from our analysis, a dashboard holding the same items, and a cited assistant for everything they raise.

  • Federal Register, Federal Register+, Grants.gov, Regulations.gov, NSF News, UKRI, plus CASRAI’s own published content.
  • 44,322 indexed passages, and every answer cites the ones it drew on.