Interactive SQL practice

SQL JOIN Exercises

Practice combining related tables with INNER JOIN and LEFT JOIN exercises. These 40 interactive challenges use real schemas and instant query validation.

Practice this concept

Start with a free exercise

Employee Department NamesMore exercises on this topic

40 SQL challenges

Open Practice Arena
INNER JOIN
Intermediate

Revenue Per Customer

Calculate total revenue (sum of total_amount) per customer, showing customer name and total revenue, sorted by revenue descending. Return columns: customer_name, total_revenue. Order results by: total_revenue DESC.

INNER JOIN
Intermediate

Product Sales Summary

For each product, show the total quantity sold and total revenue from order_items. Include product name. Return columns: product_name, total_quantity, total_revenue. Order results by: total_revenue DESC.

INNER JOIN
Intermediate

Department Payroll Summary

Show each department name, employee count, and total payroll. Return columns: department_name, employee_count, total_payroll. Order results by: d.id.

LEFT JOIN
Intermediate

Department Employee Coverage

Show all departments and their employee count, including departments with no employees. Return columns: department_name, employee_count. Order results by: d.id.

INNER JOIN
Intermediate

Largest 1 Orders

Return the 1 orders with the highest totals, including customer names. Return columns: order_id, customer_name, total_amount. Order results by: o.total_amount DESC, o.id.

INNER JOIN
Intermediate

Largest 2 Orders

Return the 2 orders with the highest totals, including customer names. Return columns: order_id, customer_name, total_amount. Order results by: o.total_amount DESC, o.id.

INNER JOIN
Intermediate
PRO

Largest 3 Orders

Return the 3 orders with the highest totals, including customer names. Return columns: order_id, customer_name, total_amount. Order results by: o.total_amount DESC, o.id.

INNER JOIN
Intermediate
PRO

Largest 4 Orders

Return the 4 orders with the highest totals, including customer names. Return columns: order_id, customer_name, total_amount. Order results by: o.total_amount DESC, o.id.

INNER JOIN
Intermediate
PRO

Largest 5 Orders

Return the 5 orders with the highest totals, including customer names. Return columns: order_id, customer_name, total_amount. Order results by: o.total_amount DESC, o.id.

INNER JOIN
Intermediate
PRO

Largest 6 Orders

Return the 6 orders with the highest totals, including customer names. Return columns: order_id, customer_name, total_amount. Order results by: o.total_amount DESC, o.id.

INNER JOIN
Intermediate
PRO

Largest 7 Orders

Return the 7 orders with the highest totals, including customer names. Return columns: order_id, customer_name, total_amount. Order results by: o.total_amount DESC, o.id.

INNER JOIN
Intermediate
PRO

Largest 8 Orders

Return the 8 orders with the highest totals, including customer names. Return columns: order_id, customer_name, total_amount. Order results by: o.total_amount DESC, o.id.

INNER JOIN
Advanced
PRO

Marketplace Sellers Covering Every Required Category

For each marketplace, return active sellers that offer at least one active listing in every category required by that marketplace. Ignore marketplaces with no requirements. Return marketplace_id and seller_id ordered by both columns. Return columns: marketplace_id, seller_id.

INNER JOIN
Advanced
PRO

Products Frequently Bought Together Without Double Counting

Find canonical product pairs appearing together in at least two distinct completed baskets. Repeated lines for a product in one basket count once. Return product_a, product_b and basket_count, ordered by basket_count descending then product IDs. Return columns: product_a, product_b, basket_count.

INNER JOIN
Advanced
PRO

Overlapping Subscription Periods per Customer

Return every pair of subscriptions for the same customer whose inclusive active periods overlap. A NULL end_date means the subscription is still active. Return customer_id, subscription_a, subscription_b, overlap_start and overlap_end; use NULL overlap_end for an open-ended overlap. Return columns: customer_id, subscription_a, subscription_b, overlap_start, overlap_end.

INNER JOIN
Advanced
PRO

Latest Valid Address at Order Time

For every order, select the customer's address version valid at ordered_at. Validity is inclusive at valid_from and exclusive at valid_to; NULL valid_to is open-ended. If versions share valid_from, choose the highest address_id. Return order_id, address_id and city. Return columns: order_id, address_id, city.

INNER JOIN
Advanced
PRO

Support Ticket Ownership Chain

Show the complete escalation ownership for open tickets: assigned agent, that agent's team lead, and the lead's support director. Exclude tickets whose chain is incomplete. Return ticket_id, agent_name, lead_name and director_name. Return columns: ticket_id, agent_name, lead_name, director_name.

INNER JOIN
Advanced
PRO

Customers Shared Across Sales Representatives

Find canonical pairs of active sales representatives who currently share at least two distinct customers. Duplicate assignment history must not inflate the count. Return rep_a, rep_b and shared_customers. Return columns: rep_a, rep_b, shared_customers.

LEFT JOIN
Expert
PRO

Employee Manager Lookup

Use a self LEFT JOIN to list every employee with their direct manager's first name. Return columns: id, first_name, manager_name. Order results by: e.id.

INNER JOIN
Expert
PRO

Unmatched Inventory Movements Reconciliation

Reconcile ledger and scanner inventory movements by reference_code and product_id. Return records missing from either side or having different quantities. Emulate a full outer join in SQLite. Return reference_code, product_id, ledger_qty, scanner_qty and issue. Return columns: reference_code, product_id, ledger_qty, scanner_qty, issue.

Concept guide

How to practice SQL JOIN

SQL JOINs combine rows from related tables. INNER JOIN keeps matching rows, while LEFT JOIN preserves every row from the left table and fills missing matches with NULL.

What to master

  • • Choose join keys that represent the relationship
  • • Qualify shared column names with table aliases
  • • Understand how one-to-many joins affect row counts
  • • Handle unmatched rows and NULL values deliberately

A reliable problem-solving workflow

  1. 1Identify the tables and required output columns.
  2. 2Find the primary-key and foreign-key relationship.
  3. 3Choose INNER JOIN or LEFT JOIN based on whether unmatched rows must remain.
  4. 4Run the query and verify both values and row count.
What is the difference between INNER JOIN and LEFT JOIN?

INNER JOIN returns only matching rows. LEFT JOIN returns every row from the left table and matching rows from the right table, using NULL when no match exists.

Why does a SQL JOIN create duplicate rows?

A one-to-many or many-to-many relationship can produce multiple result rows for one source row. Check the join keys and the relationship cardinality.