SQL JOIN Visualizer: Watch INNER JOIN and LEFT JOIN Match Rows

A SQL JOIN pairs up rows from two tables and turns each pair into one row.

The board below is connected to a small shop database with 8 customers and 12 orders. Edit the SQL and run it, and the diagram and the result update right away.

Edit the SQL and run it

Examples

Click "JOIN" on the line between two tables to pick a join type and play back how rows are matched.

JOIN keeps only the pairs where ON is true

Each row of customers is checked against each row of orders, and every pair where the ON condition (o.customer_id = c.id) is true becomes one row of the result. Ana Ruiz and Ken Aoki have no orders, so they never form a pair and do not appear in the result.

The playback shows four customers. With all the data, the result has 12 rows.

LEFT JOIN also keeps left rows with no match

A LEFT JOIN keeps every row of the table on the left (customers, after FROM). Ana Ruiz and Ken Aoki have no orders to pair with, but they still get one row each, with the orders columns filled with NULL (a marker for a missing value). With all the data, the 12 rows from the JOIN plus these 2 rows make 14.

To get only the rows with no match, use that NULL. The board’s “Customers with no orders” example runs WHERE o.id IS NULL after the LEFT JOIN to keep only the rows whose order columns are NULL.

Why a JOIN adds rows

The Venn diagrams often used to explain JOIN show which table keeps its rows. They cannot show how many pairs of rows are made. Liam Carter has three orders, so ON is true for three pairs, and Liam Carter appears in three rows of the result.

SELECT c.id, c.name, o.id, o.status
FROM customers c
JOIN orders o ON o.customer_id = c.id;

Watch for this repetition when you count joined rows. After a LEFT JOIN, count(*) counts the NULL-filled row of a customer with no orders, so that customer gets 1. The board’s “Orders per customer” example counts count(o.id) instead, which gives 0 for customers with no orders.

In a LEFT JOIN, ON and WHERE give different results

A condition on the right table in WHERE filters rows after the pairs are made. Rows with no match have a NULL o.status, so o.status = 'shipped' is never true and those customers drop out. In ON, the condition applies while the pairs are made. Customers with no shipped orders stay, with NULL in the order columns.

In WHERE
SELECT c.name, o.id, o.status
FROM customers c
LEFT JOIN orders o
  ON o.customer_id = c.id
WHERE o.status = 'shipped';
In ON
SELECT c.name, o.id, o.status
FROM customers c
LEFT JOIN orders o
  ON o.customer_id = c.id
 AND o.status = 'shipped';

The tables show four customers.

Join types and which rows they keep

SyntaxRows keptRows with this data
JOIN (INNER JOIN)Only pairs where ON is true12
LEFT JOINEvery row of the left table (right columns NULL when there is no match)14
RIGHT JOINEvery row of the right table (left columns NULL when there is no match)12
FULL JOINEvery row of both tables14
CROSS JOINNo ON; every possible pair (left rows × right rows)96

Every order belongs to a customer (customer_id is NOT NULL and references customers), so with this data RIGHT JOIN returns as many rows as JOIN, and FULL JOIN as many as LEFT JOIN.

FAQ

Are JOIN and INNER JOIN the same?

Yes. Writing just JOIN gives you an INNER JOIN.

What is the difference between LEFT JOIN and LEFT OUTER JOIN?

There is none. OUTER is optional, so LEFT JOIN and LEFT OUTER JOIN return the same result.

Why does a JOIN add rows?

You get one row for every pair of rows where the ON condition is true. A customer with three orders pairs with each of them, so that customer appears in three rows.

How do I get only the rows with no match?

Use a LEFT JOIN, then keep the rows where the right table’s primary key is NULL (WHERE o.id IS NULL). Rows with no match have every column from the right table filled with NULL.

How do RIGHT JOIN and FULL JOIN differ?

A RIGHT JOIN keeps every row of the right table, so swapping the tables and using a LEFT JOIN returns the same rows (with the columns in a different order). A FULL JOIN keeps every row from both tables and fills the missing side with NULL.

Is a Venn diagram a good way to explain JOIN?

It shows which table keeps all its rows. It cannot show how many pairs of rows are made, so it hides the fact that a customer with three orders becomes three rows.

Learn SQL step by step

WebTerm Learn’s SQL Introduction and SQL Fundamentals courses (both coming soon) use this board to build SQL as you go, moving like a game from SELECT to JOIN, GROUP BY and subqueries. The SQL learning guide explains where to start.

The data is the shop database used in WebTerm Learn’s SQL Introduction course. Queries run in an in-browser simulation that follows PostgreSQL, and any data you change on the board resets when you reload the page.