SQL joins combine rows from two or more tables based on a related column. The type of join determines which rows are included when there is no match — INNER JOIN returns only matching rows, LEFT JOIN returns all rows from the left table, and FULL OUTER JOIN returns all rows from both. This guide explains every join type with practical examples.
A SQL join combines rows from two or more tables based on a related column — a condition that determines which row in one table corresponds to which row in another. The join type determines what happens when there is no match: does the query return only the rows that match, or does it also return unmatched rows from one or both sides?
Joins are the fundamental mechanism for working with relational data. Almost every analytical query against a properly structured relational database or data warehouse requires at least one join — connecting fact tables to dimension tables, resolving foreign keys to descriptive attributes, combining measurements across related entities.
INNER JOIN
An INNER JOIN returns only the rows where the join condition matches in both tables. Rows in the left table with no matching row in the right table are excluded; rows in the right table with no matching row in the left table are excluded.
In a data warehouse context, an INNER JOIN between the orders fact table and the customer dimension (on customer_key) returns only orders with a valid customer_key — orders with a null or missing customer_key, or a customer_key that has no corresponding customer dimension row, are silently excluded from the result. For dimension tables that are expected to be complete, this is usually correct. When it is not — when missing dimension keys are a data quality issue that should be visible, not hidden — use a LEFT JOIN.
LEFT JOIN (LEFT OUTER JOIN)
A LEFT JOIN returns all rows from the left (first) table, with matching rows from the right table where a match exists. When no match exists for a left table row, the right table columns appear as NULL in the result. The left table row is never excluded.
Left joins are used when you want all rows from the primary table regardless of whether the secondary table has a match. Analytical use cases:
- All customers, with their most recent order date (customers with no orders will show NULL for order date)
- All products, with their total revenue (products with no sales will show NULL or 0 after COALESCE)
- All employees, with their manager name (employees with no manager — the top of the hierarchy — will show NULL for manager name)
The LEFT JOIN is arguably the most important join type in analytical SQL because it is the join that makes missing data visible. An INNER JOIN hides rows with no match; a LEFT JOIN shows them as NULLs that can be investigated or handled.
RIGHT JOIN (RIGHT OUTER JOIN)
A RIGHT JOIN is the mirror of a LEFT JOIN — it returns all rows from the right table, with matching rows from the left table where a match exists. When no match exists for a right table row, left table columns appear as NULL.
In practice, RIGHT JOINs are rarely used. Any RIGHT JOIN can be rewritten as a LEFT JOIN by swapping the table order. Most SQL style conventions prefer LEFT JOINs consistently for readability — the "primary" table is always on the left.
FULL OUTER JOIN
A FULL OUTER JOIN returns all rows from both tables. Where matches exist, left and right columns are populated. Where no match exists, the non-matching side's columns appear as NULL.
Full outer joins are used for reconciliation: comparing two datasets to find rows in one that are not in the other, and vice versa. Identifying records in system A not in system B, and records in system B not in system A, simultaneously.
CROSS JOIN
A CROSS JOIN produces the Cartesian product of two tables — every row from the left table combined with every row from the right table. No join condition. A table with 1,000 rows cross-joined to a table with 365 rows produces 365,000 rows.
Cross joins are occasionally intentional — generating all date-product combinations for a calendar scaffold, or expanding a parameter table against every customer record for scenario modeling. Accidental cross joins (from omitting a join condition) produce very large result sets and are a common source of query explosions.
JOIN ON vs USING vs NATURAL JOIN
**ON:** The explicit condition — ON a.customer_key = b.customer_key. Most readable and least error-prone.
**USING:** Shorthand when both tables have a column with the same name and that column is the join key — USING (customer_key). Equivalent to ON a.customer_key = b.customer_key but does not require table qualification. Supported by most databases.
**NATURAL JOIN:** Automatically joins on all columns with the same name in both tables. Almost never used in production — fragile, because adding a column with the same name to either table changes join behavior silently.
Self Joins
A self join joins a table to itself — typically to resolve hierarchical or recursive relationships within the same table. An employees table with a manager_id column that references another employee_id in the same table: SELECT e.name, m.name as manager_name FROM employees e LEFT JOIN employees m ON e.manager_id = m.employee_id joins the table to itself to retrieve the manager's name.
Join Performance
Join performance in cloud data warehouses (BigQuery, Snowflake, Redshift) depends primarily on:
- The data volume on each side of the join
- Whether the join uses partition/cluster keys (enables pruning before the join)
- The join cardinality (one-to-many joins are efficient; many-to-many joins can produce unexpected result set sizes)
For data warehouse star schema joins — fact table to dimension table on an integer surrogate key — performance is generally excellent because dimension tables are small and the join key is a simple integer equality.
Our data engineering services designs SQL transformation models with correct join logic and performance-appropriate join strategies. Contact us to discuss your data engineering requirements.
A former Microsoft data architect audits your data foundation, identifies your top priorities, and sends you a written plan. Free. No pitch.
Book a Call →