MySQL CROSS JOIN returns every possible combination of rows from two tables. It does not require an ON condition because it is not matching rows by a key.
SELECT p.p_id,
p.product,
s.sale_id,
s.product AS sold_product
FROM products AS p
CROSS JOIN sales AS s;
If products has 8 rows and sales has 9 rows, the CROSS JOIN returns:
8 x 9 = 72 rows
SELECT table1.column1,
table2.column2
FROM table1
CROSS JOIN table2;
Unlike INNER JOIN, LEFT JOIN, and RIGHT JOIN, a CROSS JOIN normally has no ON clause. Its purpose is to create the Cartesian product of the input rows.
The examples use the existing Plus2net products and sales sample tables.
Download sample tables and data
| p_id | product | price |
|---|---|---|
| 1 | Hard Disk | 80 |
| 2 | RAM | 90 |
| 3 | Monitor | 75 |
| 4 | CPU | 55 |
| 5 | Keyboard | 20 |
| 6 | Mouse | 10 |
| 7 | Motherboard | 50 |
| 8 | Power supply | 20 |
| sale_id | c_id | p_id | product | qty | store |
|---|---|---|---|---|---|
| 1 | 2 | 3 | Monitor | 2 | ABC |
| 2 | 2 | 4 | CPU | 1 | DEF |
| 3 | 1 | 3 | Monitor | 3 | ABC |
| 4 | 4 | 2 | RAM | 2 | DEF |
| 5 | 2 | 3 | Monitor | 3 | ABC |
| 6 | 3 | 3 | Monitor | 2 | DEF |
| 7 | 2 | 2 | RAM | 3 | ABC |
| 8 | 3 | 2 | RAM | 2 | DEF |
| 9 | 2 | 3 | Monitor | 2 | ABC |
The original page contained a typo, SLECT. The correct query is:
SELECT p.p_id,
p.product AS catalog_product,
p.price,
s.sale_id,
s.p_id AS sale_p_id,
s.product AS sold_product,
s.qty,
s.store
FROM products AS p
CROSS JOIN sales AS s
ORDER BY s.sale_id, p.p_id;
Every product is paired with every sale, so 8 product rows x 9 sales rows = 72 result rows.
| p_id | catalog_product | price | sale_id | sale_p_id | sold_product | qty | store |
|---|---|---|---|---|---|---|---|
| 1 | Hard Disk | 80 | 1 | 3 | Monitor | 2 | ABC |
| 2 | RAM | 90 | 1 | 3 | Monitor | 2 | ABC |
| 3 | Monitor | 75 | 1 | 3 | Monitor | 2 | ABC |
| View the complete 72-row sample output | |||||||
For an unfiltered CROSS JOIN, the theoretical number of output rows is:
rows in table A x rows in table B
You can also ask MySQL to count the combinations:
SELECT COUNT(*) AS combinations
FROM products
CROSS JOIN sales;
With 8 and 9 source rows, combinations is 72.
See MySQL COUNT() for more counting patterns.
A WHERE clause filters combinations after the Cartesian product is logically formed.
The sample sales table has five rows where qty = 2. Each of those five rows is paired with all eight products:
SELECT p.p_id,
p.product AS catalog_product,
s.sale_id,
s.product AS sold_product,
s.qty,
s.store
FROM products AS p
CROSS JOIN sales AS s
WHERE s.qty = 2
ORDER BY s.sale_id, p.p_id;
The result contains:
8 products x 5 qualifying sales = 40 rows
| p_id | catalog_product | sale_id | sold_product | qty | store |
|---|---|---|---|---|---|
| 1 | Hard Disk | 1 | Monitor | 2 | ABC |
| 2 | RAM | 1 | Monitor | 2 | ABC |
| 3 | Monitor | 1 | Monitor | 2 | ABC |
| View the complete 40-row sample output | |||||
Both sample tables contain p_id and product, so table aliases are important whenever a query refers to one of those columns.
SELECT p.p_id,
p.product AS catalog_product,
s.sale_id,
s.product AS sold_product,
s.qty
FROM products AS p
CROSS JOIN sales AS s
WHERE p.p_id = 2
ORDER BY s.sale_id;
Only one product has p_id = 2, and it is paired with all 9 sales rows. The result therefore has 9 rows.
SELECT p.p_id,
p.product AS catalog_product,
s.sale_id,
s.p_id AS sale_p_id,
s.product AS sold_product,
s.qty
FROM products AS p
CROSS JOIN sales AS s
WHERE s.p_id = 2
ORDER BY s.sale_id, p.p_id;
Three sales rows have p_id = 2, and each is paired with 8 products:
3 x 8 = 24 rows
View the complete 24-row sample output.
A CROSS JOIN followed by a WHERE condition that relates the two tables can produce the same result as an INNER JOIN.
For example:
SELECT p.p_id,
p.product,
s.sale_id,
s.qty
FROM products AS p
CROSS JOIN sales AS s
WHERE p.p_id = s.p_id;
is logically equivalent for this equality condition to:
SELECT p.p_id,
p.product,
s.sale_id,
s.qty
FROM products AS p
INNER JOIN sales AS s
ON p.p_id = s.p_id;
When only a small subset from one side is needed, writing the query so that the intended subset is clear can make the Cartesian size easier to reason about.
For example, pair every product with only sales where quantity is 2:
SELECT p.p_id,
p.product,
s.sale_id,
s.qty
FROM products AS p
CROSS JOIN (
SELECT sale_id,
qty
FROM sales
WHERE qty = 2
) AS s
ORDER BY s.sale_id, p.p_id;
MySQL's optimizer may choose its own efficient execution strategy, but this form makes the intended input set obvious to the reader: 8 product rows crossed with 5 qualifying sales rows.
CROSS JOIN is useful when the application really needs all combinations, for example:
SELECT s.size_name,
c.color_name
FROM sizes AS s
CROSS JOIN colors AS c
ORDER BY s.size_name, c.color_name;
If there are 4 sizes and 5 colors, this creates 20 possible combinations.
CROSS JOIN can combine more than two tables:
SELECT s.size_name,
c.color_name,
m.material_name
FROM sizes AS s
CROSS JOIN colors AS c
CROSS JOIN materials AS m;
If the tables contain 4 sizes, 5 colors and 3 materials, the result contains:
4 x 5 x 3 = 60 combinations
Each additional CROSS JOIN multiplies the possible result size, so row counts should be estimated before using the query on large tables.
| Join type | Purpose |
|---|---|
| CROSS JOIN | Return every combination of rows from the input tables. |
| INNER JOIN | Return only row combinations that satisfy the ON condition. |
| LEFT JOIN | Preserve every left-table row and attach matching right rows. |
| RIGHT JOIN | Preserve every right-table row and attach matching left rows. |
SELECT *.LIMIT while inspecting an unfamiliar CROSS JOIN, but do not mistake LIMIT for a fix for an incorrectly large query.EXPLAIN and actual measurements for important production queries.SELECT p.p_id,
p.product,
s.sale_id
FROM products AS p
CROSS JOIN sales AS s
LIMIT 20;
This lets you inspect a small sample, but the underlying unfiltered cross product still represents all possible combinations.
A missing join relationship can produce an unexpectedly huge result. If two tables are related by keys, use an explicit INNER, LEFT, or RIGHT JOIN with an ON condition.
It does not. Identically named columns have no special meaning to CROSS JOIN.
The result can contain repeated column names such as two p_id and two product columns. Select and alias the required columns explicitly.
If five sales rows survive a filter and there are eight products, the result still contains 40 combinations.
If the WHERE clause is simply p.p_id = s.p_id, write that relationship with INNER JOIN ... ON for clarity.
LIMIT restricts returned rows; it does not change the meaning of the CROSS JOIN. Design the query correctly first.
Download the existing product and sales SQL dump
72-row CROSS JOIN sample
40-row filtered sample
24-row filtered sample
It returns every possible combination of rows from the input tables.
No. A normal CROSS JOIN has no matching condition. Its purpose is to create the Cartesian product.
For two unfiltered tables, multiply their row counts. Eight rows crossed with nine rows produces 72 combinations.
Yes. WHERE filters the combinations. If the WHERE condition relates the two tables by their keys, an explicit INNER JOIN is usually clearer.
CROSS JOIN creates every combination. INNER JOIN returns only combinations that satisfy its ON condition.
The result size multiplies rapidly. Two tables containing 10,000 and 5,000 rows can represent 50 million combinations before additional filtering.
Yes. Each additional table multiplies the number of possible combinations by that table's row count.
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.