In JOIN ... USING (dept_id), how must you reference dept_id, and is d.dept_id portable?
answer
- the column changes owner, not value
- it no longer belongs to either table
- bare name works, prefix is the risky part
- engines disagree about the table prefix
- under LEFT JOIN the merged value is coalesced
basics
~20 sThe standard makes the USING column a column of the join, referenced unqualified as dept_id. Qualifying it is not portable: Oracle rejects a qualifier on a USING column, while PostgreSQL resolves it to that table's own copy.
solid answer
~40 sAfter `emp e JOIN dept d USING (dept_id)`, the two `dept_id` columns are merged into one column that belongs to the join rather than to `e` or `d`. The portable reference is the bare name — `SELECT dept_id`, `WHERE dept_id = 10`, `ORDER BY dept_id` — and it is unambiguous, unlike the same reference after an `ON` join. Qualified forms are where engines diverge: Oracle raises an error if you put a table qualifier on a `USING` column, whereas PostgreSQL still lets `e.dept_id` refer to that table's own underlying column. In an outer join the distinction is not cosmetic: after `LEFT JOIN dept d USING (dept_id)`, the merged `dept_id` is never NULL for a surviving left row, but `d.dept_id` (where the engine allows it) is NULL for unmatched rows.
code
sql · 6 lines-- portable: the merged column is referenced unqualified
SELECT dept_id, COUNT(*) AS headcount
FROM emp e
JOIN dept d USING (dept_id)
GROUP BY dept_id
ORDER BY dept_id;go deeper
Remember the practical rule: after USING (col), write col on its own without a table prefix. That form is unambiguous and works everywhere.
Explain why: the merged column is scoped to the join rather than to either table, so a qualifier is at best engine-specific. Know that SELECT * lists the merged columns first.
Demonstrate the outer-join consequence — the merged key is coalesced, so anti-join detection must test a non-key column of the other side. That is a real production bug, not trivia.
Decide whether USING belongs in the house style at all: it buys readability but ties you to name symmetry and to engines that implement it, and it makes qualified-reference behaviour a portability risk you now own.
## Where the column lives The key idea behind `USING` is a scoping rule, not a filtering rule. In `emp e JOIN dept d ON e.dept_id = d.dept_id`, the join result contains two columns named `dept_id`, each still owned by its table. In `emp e JOIN dept d USING (dept_id)`, the standard says the pair is **coalesced into a single column of the join itself**. It is no longer `e`'s column or `d`'s column; it is the join's column. Everything else follows from that. ## The portable reference is unqualified Because the merged column belongs to the join, you name it plainly: ```sql SELECT dept_id, COUNT(*) AS headcount FROM emp e JOIN dept d USING (dept_id) WHERE dept_id <> 0 GROUP BY dept_id ORDER BY dept_id; ``` No qualifier, no ambiguity error. This is a genuine ergonomic win over `ON`, where the identical `SELECT dept_id` is rejected because two visible columns answer to the name. ## Qualified references are where engines disagree Candidates often assume `e.dept_id` is simply illegal after `USING`. The honest answer is that it is **not portable**: - Oracle rejects a qualifier on a column that appears in the `USING` clause and raises an error. - PostgreSQL keeps the underlying table columns addressable, so `e.dept_id` and `d.dept_id` both resolve — to the individual source columns, not to the merged one. So the rule to carry into an interview and into a codebase is: reference a `USING` column unqualified; if you find yourself needing to name one side specifically, that is a signal to write `ON` instead, where both columns are plainly addressable everywhere. ## Why it matters more in an outer join Under an inner join the merged column and both source columns always hold the same value, so the distinction is invisible. Under an outer join it is load-bearing. The standard defines the merged column as the coalesce of the two sides, which means: ```sql SELECT dept_id -- merged: never NULL for a surviving emp row FROM emp e LEFT JOIN dept d USING (dept_id); ``` The merged `dept_id` shows the employee's department id even when no matching `dept` row exists. If you wanted to *detect* the unmatched rows, the merged column cannot help you — it is never NULL there. You test some other column of the preserved-side-opposite table instead: ```sql SELECT dept_id FROM emp e LEFT JOIN dept d USING (dept_id) WHERE d.dept_name IS NULL; -- employees whose department row is missing ``` This is the single most common `USING` bug in real code: someone writes `WHERE d.dept_id IS NULL` expecting the classic anti-join idiom, and on an engine that resolves `d.dept_id` to the underlying column it works, while on one that rejects the qualifier the statement will not even parse. Testing a non-key column of the right table is unambiguous and works either way. ## SELECT * and column order The merged column also changes what `SELECT *` produces. The standard orders the join's output as: the merged columns (in the order listed in `USING`), then the remaining columns of the left table, then the remaining columns of the right. So `SELECT *` after `USING (dept_id)` starts with `dept_id` and never repeats it. That is why long chains of joins on a shared key stay readable with `USING` and become noisy with `ON`. ## NATURAL JOIN inherits all of this `NATURAL JOIN` is defined as `USING` over every column name the two tables share, so its matched columns are merged and scoped in exactly the same way — one output column each, referenced unqualified, coalesced under an outer join. The scoping is the good part of `NATURAL JOIN`; the implicit column list is the dangerous part. ## Practical habits 1. Reference `USING` columns unqualified, always. 2. Do not use the merged key column to detect unmatched rows in an outer join — it is coalesced. Test a non-key column from the other side. 3. If a query needs to distinguish the two sides' copies of the key, write `ON` and qualify both explicitly; that is what `ON` is for. 4. Remember SQL Server's join syntax has no `USING` at all, so a codebase that must run there uses `ON` throughout.
- After a LEFT JOIN ... USING (dept_id), can you still tell matched rows from unmatched ones?Yes, but not via the merged key — it is the coalesce of both sides, so it holds the left value even when nothing matched. Test a column that only the right table has, such as `WHERE d.dept_name IS NULL`. That reference is unambiguous and works on every engine, whereas a qualified reference to the key column itself is not portable.
- How does the column order of SELECT * change when you switch from ON to USING?With `USING`, the standard puts the merged columns first, in the order they were listed, then the left table's remaining columns, then the right table's. With `ON`, the output is simply the left table's columns followed by the right table's, including both copies of the key. Any code depending on positional column order will see the difference.
saying these in an interview costs you the question
- Says the merged column still belongs to the left table
- Uses WHERE d.key IS NULL as an anti-join test after USING
- Claims a table qualifier on a USING column works everywhere
- Thinks USING removes the key column from the result entirely
- Assumes SELECT * column order is unchanged by USING