PRO SQL Modules
SQL Basics1h 20m • 4 lessons
Multiple Tables1h 40m • 5 lessons
Query Restructuring40m • 2 lessons
Data Transformation1h 40m • 5 lessons
Analytical SQL2h • 6 lessons
LEFT & RIGHT JOIN

Dan Lee
Lesson Objectives
By the end of this lesson, you will:
- Learn how to handle unmatched rows using LEFT JOIN and RIGHT JOIN
- Understand how to keep all records from one table while joining with another
- Write SQL queries to analyze Google Ads campaign data, including users without campaigns
🎬 Scenario: Identifying Users Without Campaigns
Your manager at Google Ads, Jordan, wants to analyze all advertisers, including those who haven’t launched any ad campaigns yet.
I need a report that includes all registered advertisers, even if they don’t have active campaigns. Can you make sure those users appear in the report?
Your task is to use LEFT JOIN to include users with and without campaigns.
Table: google_ads_campaigns
campaign_id | user_id | campaign_name | ad_type | start_date | end_date | budget | impressions | clicks | conversions |
---|---|---|---|---|---|---|---|---|---|
1 | 1 | “Growth Hackers Special” | “Search” | “2024-01-10T00:00:00” | “2024-02-10T00:00:00” | 5000 | 500000 | 12000 | 800 |
2 | 2 | “BigTech Awareness” | “Display” | “2024-01-05T00:00:00” | “2024-02-20T00:00:00” | 20000 | 2000000 | 50000 | 3000 |
3 | 3 | “Ecom Holiday Sales” | “Shopping” | “2023-11-15T00:00:00” | “2024-01-15T00:00:00” | 10000 | 750000 | 22000 | 1500 |
4 | 4 | “Fashion Hub Summer” | “Video” | “2024-02-01T00:00:00” | “2024-03-01T00:00:00” | 15000 | 900000 | 18000 | 1200 |
5 | 5 | “HealthyLife Brand Push” | “Search” | “2024-01-20T00:00:00” | “2024-03-10T00:00:00” | 8000 | 600000 | 15000 | 900 |
Table: google_ads_users
user_id | name | company | country | signup_date | ad_spend_total | is_active | |
---|---|---|---|---|---|---|---|
1 | “Alice Johnson” | “alice@startupx.com” | “StartupX” | “USA” | “2021-06-15T00:00:00” | 50000 | true |
2 | “Bob Smith” | “bob@bigtech.com” | “BigTech Corp” | “Canada” | “2020-03-20T00:00:00” | 200000 | true |
3 | “Charlie Lee” | “charlie@ecomstore.com” | “EcomStore” | “UK” | “2019-11-01T00:00:00” | 75000 | false |
4 | “David Kim” | “david@fashionhub.com” | “FashionHub” | “Germany” | “2022-05-30T00:00:00” | 120000 | true |
5 | “Emma Garcia” | “emma@healthylife.com” | “HealthyLife” | “Mexico” | “2023-02-12T00:00:00” | 30000 | true |
1. Understanding LEFT JOIN & RIGHT JOIN
Unlike INNER JOIN, which only returns matching records, LEFT JOIN and RIGHT JOIN keep unmatched rows from one table.
Join Type | Keeps All Rows From | Includes Matches From | Unmatched Rows Appear As |
---|---|---|---|
LEFT JOIN | Left table | Right table | NULL in right table columns |
RIGHT JOIN | Right table | Left table | NULL in left table columns |
Syntax
1SELECT table1.column1, table2.column2
2FROM table1
3LEFT JOIN table2
4ON table1.common_key = table2.common_key;
- LEFT JOIN keeps all rows from the left table, filling in NULL for non-matching rows from the right table.
- RIGHT JOIN does the same but keeps all rows from the right table.
2. Using LEFT JOIN to Include All Users
We want to list all advertisers, even those without ad campaigns.
Example Query: Showing Users With and Without Campaigns
1SELECT u.user_id, u.name, u.company, c.campaign_name, c.budget
2FROM google_ads_users u
3LEFT JOIN google_ads_campaigns c
4ON u.user_id = c.user_id;
user_id | name | company | campaign_name | budget |
---|---|---|---|---|
1 | Alice Johnson | StartupX | Growth Hackers Special | 5000 |
2 | Bob Smith | BigTech Corp | BigTech Awareness | 20000 |
3 | Charlie Lee | EcomStore | Ecom Holiday Sales | 10000 |
4 | David Kim | FashionHub | Fashion Hub Summer | 15000 |
5 | Emma Garcia | HealthyLife | HealthyLife Brand Push | 8000 |
What’s Happening?
- LEFT JOIN keeps all users, even if they don’t have an ad campaign.
- Users without campaigns will have NULL for campaign_name and budget.
3. Using RIGHT JOIN to Include All Campaigns
We can also ensure all campaigns appear, even if they aren’t linked to a user (hypothetically, if campaigns were assigned differently).
Example Query: Ensuring All Campaigns Are Listed
1SELECT c.campaign_id, c.campaign_name, u.name, u.company
2FROM google_ads_campaigns c
3RIGHT JOIN google_ads_users u
4ON c.user_id = u.user_id;
campaign_id | campaign_name | name | company |
---|---|---|---|
1 | Growth Hackers Special | Alice Johnson | StartupX |
2 | BigTech Awareness | Bob Smith | BigTech Corp |
3 | Ecom Holiday Sales | Charlie Lee | EcomStore |
4 | Fashion Hub Summer | David Kim | FashionHub |
5 | HealthyLife Brand Push | Emma Garcia | HealthyLife |
What’s Happening?
- RIGHT JOIN keeps all campaigns, even if they aren’t linked to an active advertiser.
- Advertisers without campaigns will appear as NULL.
4. Joining More Than Two Tables
Sometimes, we need to join multiple tables to get a more comprehensive dataset.
For example, to analyze advertisers, their campaigns, and clicks, we need to join:
- google_ads_users → Contains advertiser details.
- google_ads_campaigns → Contains campaign details.
- google_ads_clicks → Contains click activity.
Example Query: Connecting Users, Campaigns, and Clicks
1SELECT u.name, u.company, c.campaign_name, cl.click_id, cl.device_type, cl.converted
2FROM google_ads_users u
3LEFT JOIN google_ads_campaigns c
4ON u.user_id = c.user_id
5LEFT JOIN google_ads_clicks cl
6ON c.campaign_id = cl.campaign_id;
name | company | campaign_name | click_id | device_type | converted |
---|---|---|---|---|---|
“Alice Johnson” | “StartupX” | “Growth Hackers Special” | 1 | “Mobile” | false |
“Alice Johnson” | “StartupX” | “Growth Hackers Special” | 2 | “Desktop” | true |
“Bob Smith” | “BigTech Corp” | “BigTech Awareness” | 3 | “Tablet” | false |
“Bob Smith” | “BigTech Corp” | “BigTech Awareness” | 4 | “Mobile” | true |
“Charlie Lee” | “EcomStore” | “Ecom Holiday Sales” | 5 | “Desktop” | false |
“Charlie Lee” | “EcomStore” | “Ecom Holiday Sales” | 6 | “Mobile” | true |
“David Kim” | “FashionHub” | “Fashion Hub Summer” | 7 | “Mobile” | false |
“David Kim” | “FashionHub” | “Fashion Hub Summer” | 8 | “Tablet” | false |
“Emma Garcia” | “HealthyLife” | “HealthyLife Brand Push” | 9 | “Desktop” | true |
“Emma Garcia” | “HealthyLife” | “HealthyLife Brand Push” | 10 | “Mobile” | false |
“Bob Smith” | “BigTech Corp” | “BigTech Awareness” | 11 | “Mobile” | true |
“Alice Johnson” | “StartupX” | “Growth Hackers Special” | 12 | “Tablet” | false |
What’s Happening?
- LEFT JOIN ensures that all advertisers appear in the dataset.
- Campaigns without clicks will have NULL values in the click_id column.
✍️ SQL Exercises
Exercise 1: Listing All Advertisers, Even Without Campaigns
Jordan needs a report that includes all advertisers, even if they haven’t launched a campaign.
Filter condition:
- Retrieve user name, company, and campaign name.
- Users without campaigns should still appear.
- Sort by company in ascending order.
name | company | campaign_name |
---|---|---|
Alice Johnson | StartupX | Growth Hackers Special |
Bob Smith | BigTech Corp | BigTech Awareness |
Charlie Lee | EcomStore | Ecom Holiday Sales |
David Kim | FashionHub | Fashion Hub Summer |
Emma Garcia | HealthyLife | HealthyLife Brand Push |
Write an SQL query to return the requested data.
Exercise 2: Joining Multiple Tables for Click Data
Jordan wants to see advertisers, their campaigns, and clicks.
Filter condition:
- Retrieve advertiser name, company, campaign name, and click ID.
- Include all advertisers, even if they haven’t received clicks.
- Sort by click_id in ascending order.
name | company | campaign_name | click_id |
---|---|---|---|
“Alice Johnson” | “StartupX” | “Growth Hackers Special” | 1 |
“Alice Johnson” | “StartupX” | “Growth Hackers Special” | 2 |
“Bob Smith” | “BigTech Corp” | “BigTech Awareness” | 3 |
“Bob Smith” | “BigTech Corp” | “BigTech Awareness” | 4 |
“Charlie Lee” | “EcomStore” | “Ecom Holiday Sales” | 5 |
“Charlie Lee” | “EcomStore” | “Ecom Holiday Sales” | 6 |
“David Kim” | “FashionHub” | “Fashion Hub Summer” | 7 |
“David Kim” | “FashionHub” | “Fashion Hub Summer” | 8 |
“Emma Garcia” | “HealthyLife” | “HealthyLife Brand Push” | 9 |
“Emma Garcia” | “HealthyLife” | “HealthyLife Brand Push” | 10 |
“Bob Smith” | “BigTech Corp” | “BigTech Awareness” | 11 |
“Alice Johnson” | “StartupX” | “Growth Hackers Special” | 12 |
Write an SQL query to return the requested data.