Skip to main content

Outer Joins

Updated Aug 28, 2019 ·

Sample Tables

Here is the schema for the sample leaderships table:

To download the actual files, you can get them from my Github repository.

LEFT JOIN

LEFT JOIN lets you retrieve records from both tables even if there’s no match on the joining field. It returns all records from the left table and the matching records from the right table.

From the example above, we can see that the result of a LEFT JOIN on the id field shows that it includes all records from the left table. On the other hand, an INNER JOIN will only return the records with matches.

Syntax:

SELECT *
FROM left_table
LEFT JOIN right_table
ON left_table.id = right_table.id;

Using the tables in the leadership database, if we want to include all countries with prime ministers and optionally presidents, LEFT JOIN is appropriate. The syntax is similar to INNER JOIN, just replace INNER with LEFT. LEFT JOIN can also be written as LEFT OUTER JOIN.

  • The syntax is similar to INNER JOIN; use LEFT instead of INNER.
  • It returns null values for missing matches.
  • LEFT JOIN can also be written as LEFT OUTER JOIN.

Query:

SELECT p1.country, prime_minister, president
FROM prime_ministers AS p1
LEFT JOIN presidents AS p2
USING (country);

Output:

prime_ministerpresident
United KingdomNULL
CanadaNULL
AustraliaNULL
IndiaRam Nath Kovind
JapanNULL
GermanyFrank-Walter Steinmeier
ItalySergio Mattarella
South AfricaNULL
New ZealandNULL
SpainNULL
BelgiumNULL
SwedenNULL

RIGHT JOIN

RIGHT JOIN is less commonly used compared to LEFT JOIN. RIGHT JOIN keeps all records from the right table, even if there are no matches in the left table.

  • RIGHT JOIN includes all records from the right table.
  • Null values are returned for unmatched records from the left table.
  • RIGHT JOIN can also be written as RIGHT OUTER JOIN.

The syntax for RIGHT JOIN follows a similar pattern to LEFT JOIN but reverses the roles of the tables. It can also be written as RIGHT OUTER JOIN.

Syntax:

SELECT *
FROM left_table
RIGHT JOIN right_table
ON left_table.id = right_table.id;

In the leadership table example, performing a RIGHT JOIN between prime ministers and presidents will include null values where countries have presidents but no prime ministers.

Query:

SELECT p1.country, prime_minister, president
FROM prime_ministers AS p1
RIGHT JOIN presidents AS p2
USING (country);

Output:

countryprime_ministerpresident
USANULLJoe Biden
FranceNULLEmmanuel Macron
South KoreaNULLMoon Jae-in
IndiaNarendra ModiRam Nath Kovind
GermanyAngela MerkelFrank-Walter Steinmeier
ItalyMario DraghiSergio Mattarella
BrazilNULLJair Bolsonaro
MexicoNULLAndrés Manuel López Obrador
ChinaNULLXi Jinping
RussiaNULLVladimir Putin

LEFT JOIN vs. RIGHT JOIN

While both LEFT JOIN and RIGHT JOINs are useful, RIGHT JOIN is less common because it can always be converted to a LEFT JOIN.

  • LEFT JOIN is often more intuitive
  • Due to the natural left-to-right flow of writing and reading queries.
  • RIGHT JOIN is less commonly used as LEFT JOIN can achieve the same results.

More Examples

The World Economies database contain the tables below. To limit the number of results in the examples, each table only has 20 records.

countries table
codenamecontinentregionsurface_areaindep_yearlocal_namegov_formcapitalcap_longcap_lat
AFGAfghanistanAsiaSouthern and Central Asia6520901919Afganistan/AfqanestanIslamic EmirateKabul69.176134.5228
NLDNetherlandsEuropeWestern Europe415261581NederlandConstitutional MonarchyAmsterdam4.8909552.3738
ALBAlbaniaEuropeSouthern Europe287481912ShqiperiaRepublicTirane19.817241.3317
DZAAlgeriaAfricaNorthern Africa23817401962Al-Jaza’ir/AlgerieRepublicAlgiers3.0509736.7397
ASMAmerican SamoaOceaniaPolynesia199nullAmerika SamoaUS TerritoryPago Pago-170.691-14.2846
ANDAndorraEuropeSouthern Europe4681278AndorraParliamentary CoprincipalityAndorra la Vella1.521842.5075
AGOAngolaAfricaCentral Africa12467001975AngolaRepublicLuanda13.242-8.81155
ATGAntigua and BarbudaNorth AmericaCaribbean4421981Antigua and BarbudaConstitutional MonarchySaint John's-61.845617.1175
AREUnited Arab EmiratesAsiaMiddle East836001971Al-Imarat al-´Arabiya al-MuttahidaEmirate FederationAbu Dhabi54.370524.4764
ARGArgentinaSouth AmericaSouth America27804001816ArgentinaFederal RepublicBuenos Aires-58.4173-34.6118
ARMArmeniaAsiaMiddle East298001991HajastanRepublicYerevan44.50940.1596
ABWArubaNorth AmericaCaribbean193nullArubaNonmetropolitan Territory of The NetherlandsOranjestad-70.016712.5167
AUSAustraliaOceaniaAustralia and New Zealand77412201901AustraliaConstitutional Monarchy, FederationCanberra149.129-35.282
AZEAzerbaijanAsiaMiddle East866001991AzarbaycanFederal RepublicBaku49.893240.3834
BHSBahamasNorth AmericaCaribbean138781973The BahamasConstitutional MonarchyNassau-77.33925.0661
BHRBahrainAsiaMiddle East6941971Al-BahraynMonarchy (Emirate)Manama50.535426.1921
BGDBangladeshAsiaSouthern and Central Asia1439981971BangladeshRepublicDhaka90.411323.7055
BRBBarbadosNorth AmericaCaribbean4301966BarbadosConstitutional MonarchyBridgetown-59.610513.0935
BELBelgiumEuropeWestern Europe305181830Belgie/BelgiqueConstitutional Monarchy, FederationBrussels4.3676150.8371
BLZBelizeNorth AmericaCentral America226961981BelizeConstitutional MonarchyBelmopan-88.771317.2534
cities table
namecountry_codecity_proper_popmetroarea_popurbanarea_pop
AbidjanCIV4765000null4765000
Abu DhabiARE1145000null1145000
AbujaNGA123588060000001235880
AccraGHA207046340100542070463
Addis AbabaETH310367345678573103673
AhmedabadIND5570585null5570585
AlexandriaEGY4616625null4616625
AlgiersDZA341581150000003415811
AlmatyKAZ1703481null1703481
AnkaraTUR527100045850005271000
AucklandNZL149500016143001495000
BaghdadIRQ7180889null7180889
BakuAZE320230043087403202300
BandungIDN257547869656552575478
BangkokTHA8280925149980008280925
BarcelonaESP160455553757741604555
BarranquillaCOL138686523707531386865
BasraIRQ2750000null2750000
BeijingCHN215160002490000021516000
Belo HorizonteBRA250255751562172502557
economies table
econ_idcodeyearincome_groupgdp_percapitagross_savingsinflation_ratetotal_investmentunemployment_rateexportsimports
1AFG2010Low income539.66737.1332.17930.402null46.39424.381
2AFG2015Low income615.09121.466-1.54918.602null-49.11-7.294
3AGO2010Upper middle income3599.2723.53414.4814.433null-3.266-21.076
4AGO2015Upper middle income3876.2-0.42510.2879.552null6.721-21.778
5ALB2010Upper middle income4098.1320.0113.60531.3051410.645-8.013
6ALB2015Upper middle income3943.2213.841.89624.59817.11.8270.574
7ARE2010High income34628.6327.0730.87827.372null3.843-0.981
8ARE2015High income38649.9134.1064.0727.477null7.322.17
9ARG2010Upper middle income10412.9517.36110.46117.7067.7513.93139.877
10ARG2015Upper middle income14643.9214.111null16.89null-1.6583.105
11ARM2010Lower middle income3121.7815.7977.27429.4191930.1834.09
12ARM2015Lower middle income3520.9518.3063.73120.95618.515.729-9.647
13ATG2010High income13531.7813.3983.37nullnull-3.241-14.113
14ATG2015High income15155.1618.7540.969nullnull6.026-24.307
15AUS2010High income56362.8423.5842.86327.0895.2085.78215.208
16AUS2015High income51363.922.1111.46126.3046.0586.0221.99
17AUT2010High income46757.1325.5211.69422.6544.813.8411.989
18AUT2015High income43749.5525.3530.8123.5075.753.5583.382
19AZE2010Upper middle income5847.2646.5675.66618.5326.048-1.792-1.459
20AZE2015Upper middle income5396.4126.44.04926.7836.0484.080.186

To download the actual files, you can get them from my Github repository.

Left Join

  1. Perform an inner join with cities AS c1 on the left and countries as c2 on the right. Use code as the field to merge your tables on.

    Solution

    Run the command below:

    SELECT 
    c1.name AS city,
    code,
    c2.name AS country,
    region,
    city_proper_pop
    FROM cities AS c1
    INNER JOIN countries AS c2
    ON c1.country_code = c2.code
    ORDER BY code DESC;

    Output (some records may not shown):

    citycodecountryregioncity_proper_pop
    HarareZWEZimbabweEastern Africa1606000
    LusakaZMBZambiaEastern Africa1742979
    Cape TownZAFSouth AfricaSouthern Africa3740026
    JohannesburgZAFSouth AfricaSouthern Africa4434827
    DurbanZAFSouth AfricaSouthern Africa3442361
    EkurhuleniZAFSouth AfricaSouthern Africa3178470
    Sana'aYEMYemenMiddle East1937451
    Ho Chi Minh CityVNMVietnamSoutheast Asia7681700
    HanoiVNMVietnamSoutheast Asia6844100
    CaracasVENVenezuelaSouth America1943901
    MaracaiboVENVenezuelaSouth America1599940
    TashkentUZBUzbekistanSouthern and Central Asia2309600
    ChicagoUSAUnited StatesNorth America2695598
    Los AngelesUSAUnited StatesNorth America3884307
    PhiladelphiaUSAUnited StatesNorth America1567872
    PhoenixUSAUnited StatesNorth America1563025
  2. Change the code to perform a LEFT JOIN instead of an INNER JOIN. After executing this query, have a look at how many records the query result contains.

    Solution

    Run the command below:

    SELECT 
    c1.name AS city,
    code,
    c2.name AS country,
    region,
    city_proper_pop
    FROM cities AS c1
    LEFT JOIN countries AS c2
    ON c1.country_code = c2.code
    ORDER BY code DESC;

    Output (some records may not shown):

    citycodecountryregioncity_proper_pop
    Taichungnullnullnull2752413
    Tainannullnullnull1885252
    Kaohsiungnullnullnull2778918
    Bucharestnullnullnull1883425
    Taipeinullnullnull2704974
    New Taipei Citynullnullnull3954929
    HarareZWEZimbabweEastern Africa1606000
    LusakaZMBZambiaEastern Africa1742979
    Cape TownZAFSouth AfricaSouthern Africa3740026
    EkurhuleniZAFSouth AfricaSouthern Africa3178470
    DurbanZAFSouth AfricaSouthern Africa3442361
    JohannesburgZAFSouth AfricaSouthern Africa4434827
  3. Order the result set by the average GDP per capita from highest to lowest. Return only the first 10 records in your result.

    Solution

    Run the command below:

    SELECT region, AVG(gdp_percapita) AS avg_gdp
    FROM countries AS c
    LEFT JOIN economies AS e
    USING(code)
    WHERE year = 2010
    GROUP BY region
    ORDER BY avg_gdp DESC
    LIMIT 10;

    Output (some records may not shown):

    RegionAvg_GDP
    Western Europe58130.96149553572
    Nordic Countries57073.99765625
    North America47911.509765625
    Australia and New Zealand44792.384765625
    British Islands43588.330078125
    Eastern Asia24962.8076171875
    Southern Europe22926.410910866478
    Middle East18204.641515395222
    Baltic Countries12631.029947916666
    Caribbean11413.339454064002

Right Join

  1. Write a new query using RIGHT JOIN that produces an identical result to the LEFT JOIN provided.

    Solution

    Run the command below:

    SELECT countries.name AS country, languages.name AS language, percent
    FROM languages
    RIGHT JOIN countries
    USING(code)
    ORDER BY language;

    Output (some records may not shown):

    CountryLanguagePercent
    EthiopiaAfar1.7
    DjiboutiAfarnull
    EritreaAfarnull
    NamibiaAfrikaans10.4
    South AfricaAfrikaans13.5
    GhanaAkyem3.2
    AlbaniaAlbanian98.8
    MacedoniaAlbanian25.1
    SwitzerlandAlbanian3
    FranceAlsatiannull
    HondurasAmerindiannull