Why this happens
Two tables, both with an id column — completely normal in a relational schema:
SELECT id, order_date
FROM orders
JOIN customers ON customers.customer_id = orders.customer_id;
-- Error: column 'id' in field list is ambiguous
Both orders and customers have their own id column. The bare word id in the SELECT list could mean either one, and SQL has no rule for guessing which — so it raises an error rather than silently picking one and possibly returning the wrong data.
The fix: qualify every reference
Prefix the column with the table name (or, more commonly, a short alias) everywhere it's ambiguous:
SELECT o.id, o.order_date
FROM orders o
JOIN customers c ON c.customer_id = o.customer_id;
Aliasing both tables (orders o, customers c) and using those aliases consistently is the standard convention — it's shorter to type than repeating the full table name and makes the query easier to scan.
It's not just SELECT
The single most common follow-up mistake: fixing the SELECT list and assuming the query is done, when the same bare column name is still ambiguous somewhere else in the statement.
SELECT o.id, o.order_date
FROM orders o
JOIN customers c ON c.customer_id = o.customer_id
ORDER BY id; -- still ambiguous — which id?
SELECT o.id, o.order_date
FROM orders o
JOIN customers c ON c.customer_id = o.customer_id
ORDER BY o.id; -- fixed
WHERE, GROUP BY, HAVING, and ORDER BY can each independently trigger this same error — every one of them needs the qualified column name if the column name exists in more than one joined table.
Does USING fix it?
JOIN ... USING (column) is a shorthand for joining on a column that exists with the same name in both tables, and it resolves ambiguity for that specific column by merging it into a single unqualified reference in the output:
SELECT customer_id, order_date -- customer_id is fine — USING merged it
FROM orders
JOIN customers USING (customer_id);
But this only helps for the join column named in USING. If both tables also happen to share a different column name — say, both have created_at — that second column is still ambiguous and still needs to be qualified explicitly.
What about SELECT *?
SELECT * across a join where both tables share a column name usually doesn't raise this specific error — it just returns duplicate column names in the result set, which is a quieter, easier-to-miss problem: most client libraries and ORMs will silently keep only one of the two same-named columns (typically the last one), discarding the other without any warning.
SELECT *, don't assume both values survive into your application code — check explicitly, or avoid SELECT * across joins entirely and name columns individually with aliases.Common mistakes
- Fixing only the SELECT list and missing the same bare column name in
WHERE,ORDER BY, orGROUP BY. - Assuming USING resolves every shared column name, when it only merges the one column explicitly named in the clause.
- Using SELECT * across joined tables with overlapping column names and not noticing a column silently disappeared from the result.
- Giving two tables in the same query the same alias by accident, which reintroduces the exact same ambiguity the alias was meant to resolve.
Key takeaways
- The error means two or more joined tables share a column name, referenced without saying which table it's from.
- The fix is qualifying the column with its table alias — everywhere it's used, not just in
SELECT. USINGresolves ambiguity only for the specific column it names, not for other shared column names.SELECT *across a join with duplicate column names doesn't raise this error, but can silently drop one of the columns.- Aliasing every table in a multi-table query and using those aliases consistently prevents this error from ever coming up.