☰ Chapters
Week 4 · Join Types
CT004-3.5-3 Advanced Database Systems · Week 4

SQL Join Types

Inner joins, multi-table joins, how a join is computed, and LEFT / RIGHT / FULL outer joins.

Contents
    Learning outcomes

    Topics: simple join · three-table join · multiple grouping columns · left / right / full outer join. Reference: Connolly & Begg, Ch. 5.

    Join types at a glance

    INNERmatches only LEFTall of left RIGHTall of right FULLeverything Left table = left circle, right table = right circle
    JoinKeepsUnmatched columns
    INNER (simple/equi-join)Only rows that match in both tables—
    LEFT OUTERAll rows of the first (left) table + matchesRight-table columns filled with NULL
    RIGHT OUTERAll rows of the second (right) table + matchesLeft-table columns filled with NULL
    FULL OUTERAll rows from both tablesEither side filled with NULL
    CROSSEvery combination (Cartesian product)—

    Simple (inner) join

    List names of all clients who have viewed a property along with any comment supplied.

    SELECT c.clientNo, fName, lName, propertyNo, comment
    FROM   Client c, Viewing v
    WHERE  c.clientNo = v.clientNo;
    clientNofNamelNamepropertyNocomment
    CR56AlineStewartPG36
    CR56AlineStewartPA14too small
    CR56AlineStewartPG4
    CR62MaryTregearPA14no dining room
    CR76JohnKayPG4too remote

    Client CR74 (Mike Ritchie) has viewed nothing, so he does not appear — that’s the key limitation that outer joins solve.

    Alternative JOIN constructs

    FROM Client c JOIN Viewing v ON c.clientNo = v.clientNo   -- explicit INNER JOIN
    FROM Client JOIN Viewing USING (clientNo)
    FROM Client NATURAL JOIN Viewing

    In each case, the FROM replaces the original FROM and WHERE. The first (ON) produces a table with two identical clientNo columns.

    Extra · ON vs USING vs NATURAL

    JOIN on its own means INNER JOIN.

    Sorting a join

    For each branch, list numbers and names of staff who manage properties, and the properties they manage.

    SELECT   s.branchNo, s.staffNo, fName, lName, propertyNo
    FROM     Staff s, PropertyForRent p
    WHERE    s.staffNo = p.staffNo
    ORDER BY s.branchNo, s.staffNo, propertyNo;
    branchNostaffNofNamelNamepropertyNo
    B003SG14DavidFordPG16
    B003SG37AnnBeechPG21
    B003SG37AnnBeechPG36
    B005SL41JulieLeePL94
    B007SA9MaryHowePA14

    Three-table join

    For each branch, list staff who manage properties, including the city in which the branch is located and the properties they manage.

    SELECT   b.branchNo, b.city, s.staffNo, fName, lName, propertyNo
    FROM     Branch b, Staff s, PropertyForRent p
    WHERE    b.branchNo = s.branchNo
      AND    s.staffNo  = p.staffNo
    ORDER BY b.branchNo, s.staffNo, propertyNo;

    Alternative formulation for FROM and WHERE:

    FROM (Branch b JOIN Staff s USING (branchNo)) AS bs
         JOIN PropertyForRent p USING (staffNo)
    branchNocitystaffNofNamelNamepropertyNo
    B003GlasgowSG14DavidFordPG16
    B003GlasgowSG37AnnBeechPG21
    B003GlasgowSG37AnnBeechPG36
    B005LondonSL41JulieLeePL94
    B007AberdeenSA9MaryHowePA14
    Rule of thumb

    Joining n tables needs at least n − 1 join conditions. Missing one gives a partial Cartesian product (far too many rows).

    Multiple grouping columns

    Find the number of properties handled by each staff member.

    SELECT   s.branchNo, s.staffNo, COUNT(*) AS myCount
    FROM     Staff s, PropertyForRent p
    WHERE    s.staffNo = p.staffNo
    GROUP BY s.branchNo, s.staffNo
    ORDER BY s.branchNo, s.staffNo;
    branchNostaffNomyCount
    B003SG141
    B003SG372
    B005SL411
    B007SA91

    Computing a join

    The conceptual procedure for generating the result of a join:

    1. Form the Cartesian product of the tables named in the FROM clause.
    2. If there is a WHERE clause, apply the search condition to each row of the product table, retaining rows that satisfy it.
    3. For each remaining row, determine the value of each item in the SELECT list to produce a single row in the result.
    4. If DISTINCT has been specified, eliminate duplicate rows.
    5. If there is an ORDER BY clause, sort the result as required.
    SELECT [DISTINCT | ALL] {* | columnList}
    FROM   Table1 CROSS JOIN Table2;   -- explicit Cartesian product
    Extra

    This is only the logical definition. Real query optimizers never build the full Cartesian product — they use nested-loop, hash or merge joins and indexes — but the result must be the same.

    Outer joins — the example tables

    With an inner join, if a row of one table is unmatched it is omitted from the result. Outer joins retain rows that do not satisfy the join condition.

    Branch1
    branchNobCity
    B003Glasgow
    B004Bristol
    B002London
    PropertyForRent1
    propertyNopCity
    PA14Aberdeen
    PL94London
    PG4Glasgow

    Inner join of these tables

    SELECT b.*, p.*
    FROM   Branch1 b, PropertyForRent1 p
    WHERE  b.bCity = p.pCity;
    branchNobCitypropertyNopCity
    B003GlasgowPG4Glasgow
    B002LondonPL94London

    The result has two rows where the cities are the same. There are no rows for the branch in Bristol or the property in Aberdeen. To include unmatched rows, use an outer join.

    LEFT OUTER JOIN

    List branches and properties that are in the same city, along with any unmatched branches.

    SELECT b.*, p.*
    FROM   Branch1 b LEFT JOIN PropertyForRent1 p
           ON b.bCity = p.pCity;
    branchNobCitypropertyNopCity
    B003GlasgowPG4Glasgow
    B004BristolNULLNULL
    B002LondonPL94London

    List branches and properties in the same city and any unmatched properties.

    SELECT b.*, p.*
    FROM   Branch1 b RIGHT JOIN PropertyForRent1 p
           ON b.bCity = p.pCity;
    branchNobCitypropertyNopCity
    NULLNULLPA14Aberdeen
    B003GlasgowPG4Glasgow
    B002LondonPL94London
    Extra

    A RIGHT JOIN B gives the same rows as B LEFT JOIN A (only column order differs). Many developers stick to LEFT JOIN for readability.

    FULL OUTER JOIN

    List branches and properties in the same city and any unmatched branches or properties.

    SELECT b.*, p.*
    FROM   Branch1 b FULL JOIN PropertyForRent1 p
           ON b.bCity = p.pCity;
    branchNobCitypropertyNopCity
    NULLNULLPA14Aberdeen
    B003GlasgowPG4Glasgow
    B004BristolNULLNULL
    B002LondonPL94London
    Exam tip — count the rows

    Inner = 2 rows. Left = 2 + 1 unmatched branch = 3. Right = 2 + 1 unmatched property = 3. Full = 2 + 1 + 1 = 4. Being able to predict these counts is a quick way to check your answer.

    Practical patterns

    Extra · finding “things with no match”

    A LEFT JOIN plus an IS NULL test finds rows with no partner — e.g. clients who have never viewed a property:

    SELECT c.clientNo, c.fName, c.lName
    FROM   Client c LEFT JOIN Viewing v ON c.clientNo = v.clientNo
    WHERE  v.clientNo IS NULL;          -- CR74 Mike Ritchie

    Counting with outer joins: use COUNT(v.propertyNo) not COUNT(*), so unmatched rows count as 0 rather than 1.

    Quick review

    What happens to unmatched rows in an inner join?
    They are omitted from the result table.
    In a LEFT JOIN, which table’s columns get NULLs?
    The second (right) table’s columns, for left rows that have no match.
    Write a query that lists every branch and every property, matched by city where possible.
    SELECT b.*, p.* FROM Branch1 b FULL JOIN PropertyForRent1 p ON b.bCity = p.pCity;
    List the 5 steps for computing a join.
    Cartesian product → apply WHERE → evaluate SELECT list → remove duplicates if DISTINCT → sort if ORDER BY.