Last Minute SQL Interview Prep Kit: Finding Nth Highest Salaries & Transaction Analysis
This chapter demystifies one of the most common and tricky SQL interview topics: how different types of joins handle duplicate keys and non-matching records. Through step-by-step scenarios, mathematical formulations, and execution flows, we will analyze how INNER JOIN, LEFT JOIN, RIGHT JOIN, and FULL OUTER JOIN calculate output row counts when tables contain duplicate values and nulls.
1. The Core Problem: How SQL Joins Handle Duplicate Keys
In SQL interviews, candidates are frequently presented with two simple tables containing duplicate keys and asked to calculate the exact number of output records for various join types. This is a classic screening question designed to test whether you truly understand the underlying mechanics of relational database engines or if you merely memorize syntax.
The Machine vs. Human Mental Model
When a human looks at two tables and is asked to join them on a key, they might intuitively try to pair them one-to-one. However, a database engine is a machine. It cannot arbitrarily decide which duplicate key in Table A matches which duplicate key in Table B.
When the database engine processes the first record (1) from T1, it scans T2 and finds three matching records (1, 1, 1). Because it cannot differentiate between these three identical values, it must join with all three. When it processes the second record (1) from T1, it repeats this process, matching with all three records in T2 again.
2. Mental Model & Mathematical Formulas for Join Calculations
To accurately predict join outputs without running the queries, we can establish a set of mathematical formulas based on key frequencies.
Let:
- be the number of times a join key appears in the Left Table ().
- be the number of times a join key appears in the Right Table ().
- be the number of unique non-matching keys in the Left Table ().
- be the number of unique non-matching keys in the Right Table ().
Mathematical Formulas by Join Type
1. Inner Join
An inner join only returns records where the join key exists in both tables. For each matching key :
2. Left Join
A left join returns all matching records plus all non-matching records from the left table (padded with NULL values for the right table's columns):
3. Right Join
A right join returns all matching records plus all non-matching records from the right table (padded with NULL values for the left table's columns):
4. Full Outer Join
A full outer join returns all matching records plus all non-matching records from both the left and right tables:
Rule of Thumb: If all keys in both tables are matching (i.e., there are no non-matching keys, meaning and ), then the output row count for all four join types will be exactly the same as the
INNER JOIN.
3. Scenario 1: Pure Duplicate Keys (No Non-Matching Records)
Let's begin with the first scenario demonstrated in the lecture, where both tables contain only matching keys with duplicate values.
Database Setup
CREATE TABLE t1 (
id INT
);
CREATE TABLE t2 (
id INT
);
-- Insert duplicate matching keys
INSERT INTO t1 (id) VALUES (1), (1);
INSERT INTO t2 (id) VALUES (1), (1), (1);
Table State
t1(Left Table): Contains two records of value1().t2(Right Table): Contains three records of value1().- Non-matching keys in
t1(): - Non-matching keys in
t2():
Join Calculations
Inner Join
SELECT t1.id AS t1_id, t2.id AS t2_id
FROM t1
INNER JOIN t2 ON t1.id = t2.id;
- Calculation: records.
- Output Row Count:
Left Join
SELECT t1.id AS t1_id, t2.id AS t2_id
FROM t1
LEFT JOIN t2 ON t1.id = t2.id;
- Calculation: records.
- Output Row Count:
Right Join
SELECT t1.id AS t1_id, t2.id AS t2_id
FROM t1
RIGHT JOIN t2 ON t1.id = t2.id;
- Calculation: records.
- Output Row Count:
Full Outer Join
SELECT t1.id AS t1_id, t2.id AS t2_id
FROM t1
FULL OUTER JOIN t2 ON t1.id = t2.id;
- Calculation: records.
- Output Row Count:
4. Scenario 2: Introducing Non-Matching Keys
Now, we introduce non-matching records to both tables to see how the join behaviors diverge. We add a value of 2 to t1 and a value of 3 to t2.
Database Setup
-- Add non-matching record to t1
INSERT INTO t1 (id) VALUES (2);
-- Add non-matching record to t2
INSERT INTO t2 (id) VALUES (3);
Table State
t1(Left Table): Contains[1, 1, 2]- (Non-matching, as
2does not exist int2) - (The record with value
2)
t2(Right Table): Contains[1, 1, 1, 3]- (Non-matching, as
3does not exist int1) - (The record with value
3)
Join Calculations
Inner Join
SELECT t1.id AS t1_id, t2.id AS t2_id
FROM t1
INNER JOIN t2 ON t1.id = t2.id;
- Calculation: Only the matching key
1is processed.
- Output Row Count:
Left Join
SELECT t1.id AS t1_id, t2.id AS t2_id
FROM t1
LEFT JOIN t2 ON t1.id = t2.id;
- Calculation: Matching records () + non-matching records from
t1( record with value2).
- Output Row Count:
- Visualizing the Output Data:
Structure & Concept Flow
Right Join
SELECT t1.id AS t1_id, t2.id AS t2_id
FROM t1
RIGHT JOIN t2 ON t1.id = t2.id;
- Calculation: Matching records () + non-matching records from
t2( record with value3).
- Output Row Count:
- Visualizing the Output Data:
Structure & Concept Flow
Full Outer Join
SELECT t1.id AS t1_id, t2.id AS t2_id
FROM t1
FULL OUTER JOIN t2 ON t1.id = t2.id;
- Calculation: Matching records () + non-matching from
t1() + non-matching fromt2().
- Output Row Count:
- Visualizing the Output Data:
Structure & Concept Flow
5. Scenario 3: Complex Duplicates on Multiple Keys
To further solidify this concept, let's add another layer of complexity by inserting another duplicate key 2 into t1, and a matching key 2 into t2.
Database Setup
-- Add another 2 to t1
INSERT INTO t1 (id) VALUES (2);
-- Add a matching 2 to t2
INSERT INTO t2 (id) VALUES (2);
Table State
t1(Left Table): Contains[1, 1, 2, 2]- (All keys in
t1now have matches int2)
t2(Right Table): Contains[1, 1, 1, 2, 3]- (Non-matching key)
- (The record with value
3)
Join Calculations
Inner Join
SELECT t1.id AS t1_id, t2.id AS t2_id
FROM t1
INNER JOIN t2 ON t1.id = t2.id;
- Calculation: We sum the products of all matching keys.
- For key
1: records. - For key
2: records.
- For key
- Output Row Count:
Left Join
SELECT t1.id AS t1_id, t2.id AS t2_id
FROM t1
LEFT JOIN t2 ON t1.id = t2.id;
- Calculation: records.
- Output Row Count:
Right Join
SELECT t1.id AS t1_id, t2.id AS t2_id
FROM t1
RIGHT JOIN t2 ON t1.id = t2.id;
- Calculation: records (the non-matching
3fromt2is appended). - Output Row Count:
Full Outer Join
SELECT t1.id AS t1_id, t2.id AS t2_id
FROM t1
FULL OUTER JOIN t2 ON t1.id = t2.id;
- Calculation: records.
- Output Row Count:
6. Tabular Synthesis of Join Behaviors
The following table synthesizes the three scenarios discussed in the lecture, showing the direct relationship between table states, join types, and output row counts.
7. Step-by-Step Execution Flow Visualizations
To understand how the database engine processes these joins row-by-row, let us trace the execution flows.
Execution Flow: Scenario 2 Left Join
This flow shows how the database evaluates each row in the Left Table (t1 containing [1, 1, 2]) against the Right Table (t2 containing [1, 1, 1, 3]).
Execution Flow: Scenario 3 Inner Join
This flow shows how the database evaluates the updated tables (t1 containing [1, 1, 2, 2] and t2 containing [1, 1, 1, 2, 3]) under an INNER JOIN constraint.
8. Summary and Key Takeaways
- The Cartesian Effect on Duplicate Keys: When joining on duplicate keys, the database engine performs a Cartesian product for that specific key. If key appears times in the left table and times in the right table, the join will produce records for that key.
- The "All-Matching" Rule of Thumb: If every key in the left table has at least one match in the right table, and every key in the right table has at least one match in the left table, then
INNER JOIN,LEFT JOIN,RIGHT JOIN, andFULL OUTER JOINwill all return the exact same number of records. - Left Join Row Count Mechanics: The row count of a
LEFT JOINis always equal to theINNER JOINrow count plus the number of non-matching records in the left table. - Right Join Row Count Mechanics: The row count of a
RIGHT JOINis always equal to theINNER JOINrow count plus the number of non-matching records in the right table. - Full Outer Join Row Count Mechanics: The row count of a
FULL OUTER JOINis the sum of theINNER JOINrow count, the non-matching left table records, and the non-matching right table records. - Handling Nulls in Joins: Non-matching records in outer joins are preserved and padded with
NULLvalues for the columns of the opposing table. - Interview Strategy: When asked this question in an interview, do not guess. Immediately write down the frequency of each key in both tables, apply the formula for each matching key, and then add the non-matching records based on the join type requested.