Home Cheat Sheets SQL Joins Cheat Sheet
📋 CHEAT SHEET

SQL Joins Cheat Sheet

Visual reference for all SQL JOIN types — INNER, LEFT, RIGHT, FULL OUTER, CROSS and SELF joins with syntax and examples.

JOIN Types Quick Reference

JOIN TypeReturnsSyntaxUse When
INNER JOINMatching rows in BOTH tablesFROM a INNER JOIN b ON a.id = b.idYou only want rows with matches on both sides
LEFT JOINAll left rows + matching rightFROM a LEFT JOIN b ON a.id = b.idKeep all left rows, even with no match
RIGHT JOINAll right rows + matching leftFROM a RIGHT JOIN b ON a.id = b.idKeep all right rows, even with no match
FULL OUTER JOINAll rows from both tablesFROM a FULL OUTER JOIN b ON a.id = b.idKeep everything, NULL where no match
CROSS JOINCartesian productFROM a CROSS JOIN bEvery combination of rows
SELF JOINTable joined to itselfFROM a t1 JOIN a t2 ON t1.id = t2.refHierarchical data, org charts

NULL Behaviour in JOINs

ScenarioINNER JOINLEFT JOINFULL OUTER JOIN
Row in left only❌ Excluded✅ Included (NULLs for right)✅ Included (NULLs for right)
Row in right only❌ Excluded❌ Excluded✅ Included (NULLs for left)
Match in both✅ Included✅ Included✅ Included
NULL join key❌ Never matches❌ Never matches❌ Never matches

Performance Tips

TipWhy It Matters
Index join columns (ON a.id = b.id)Without index, every join is a full table scan
JOIN before WHERE when possibleReduces rows early, less work for WHERE
Avoid CROSS JOIN on large tablesN×M rows — grows quadratically
Use INNER JOIN over subqueriesOptimizer handles joins better than correlated subqueries
EXPLAIN/EXPLAIN ANALYZE your joinsSee if index is being used

Common JOIN Patterns

PatternSQLUse Case
Find orphaned rowsWHERE b.id IS NULL (after LEFT JOIN)Rows in A with no matching B
Exclude matchesWHERE b.id IS NULL (after LEFT JOIN)Anti-join pattern
Count with joinSELECT COUNT(DISTINCT a.id)Avoid inflation from 1:many joins
Multiple joinsJOIN c ON b.id = c.b_idChain multiple tables

Window Functions

FunctionPurposeExample
ROW_NUMBER()Unique sequential rank (no ties)ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC)
RANK()Rank with gaps on ties (1,1,3)RANK() OVER (ORDER BY score DESC)
DENSE_RANK()Rank without gaps on ties (1,1,2)DENSE_RANK() OVER (ORDER BY score DESC)
LAG(col, n)Value from n rows before currentLAG(revenue,1) OVER (ORDER BY month) — previous month
LEAD(col, n)Value from n rows after currentLEAD(revenue,1) OVER (ORDER BY month) — next month
SUM() OVER ()Running total without collapsing rowsSUM(sales) OVER (PARTITION BY region ORDER BY date)
NTILE(n)Divide rows into n equal bucketsNTILE(4) OVER (ORDER BY score) — quartiles
FIRST_VALUE / LAST_VALUEFirst/last value in window frameFIRST_VALUE(salary) OVER (PARTITION BY dept ORDER BY hire_date)

Subquery vs JOIN

ScenarioUseReason
Filter by aggregate resultSubquery (WHERE salary > (SELECT AVG...))Aggregate not available in same WHERE clause
Combine columns from two tablesJOINOptimizer handles JOIN better; subquery re-runs per row in correlated case
EXISTS check (semi-join)EXISTS subqueryStops at first match — faster than JOIN + DISTINCT
NOT EXISTSNOT EXISTS subqueryHandles NULLs correctly — NOT IN fails if subquery has NULLs
Top-N per groupSubquery or CTE + ROW_NUMBER()JOIN approach is verbose; window function cleaner
Reuse intermediate resultCTE (WITH clause)Readable, optimizer may materialise once; cleaner than nested subquery
Correlated subquery (row-by-row)Avoid — use JOIN or window fnCorrelated subquery runs once per outer row — O(n²)
More Cheat Sheets
Java Collections Cheat SheetJava Streams API Cheat SheetPython Built-in Functions Cheat SheetDocker Commands Cheat SheetJVM Memory Model DiagramHow HashMap Works InternallyMicroservices Cheat SheetPandas Cheat SheetData Structures & Algorithms Cheat Sheet