Skip to content

MySQL - Cross Join

A MySQL CROSS JOIN produces the Cartesian product of the tables involved in the join. The result is a table where each row from the first table is combined with every single row from the second table. If the first table has N rows and the second table has M rows, the resulting table will have N * M rows.

This type of join does not have an ON clause because it doesn’t match rows based on a condition. It simply generates all possible combinations of rows from the joined tables.

Warning: Use CROSS JOIN with extreme caution. Joining even moderately-sized tables can result in an enormous number of rows, consuming significant server resources and potentially crashing your application. It is often an indication of a logical error, such as a forgotten ON clause in what was intended to be an INNER JOIN.

The basic syntax for a CROSS JOIN is straightforward:

SELECT column_name(s)
FROM table1
CROSS JOIN table2;

An older, implicit syntax also produces a Cartesian product, but the explicit CROSS JOIN syntax is preferred for clarity:

-- Implicit syntax, less readable and not recommended
SELECT column_name(s)
FROM table1, table2;

Let’s consider a scenario where we want to generate all possible combinations of shirt sizes and colors. First, we create two simple tables.

CREATE TABLE sizes (
id INT PRIMARY KEY AUTO_INCREMENT,
size_name VARCHAR(10) NOT NULL
);
CREATE TABLE colors (
id INT PRIMARY KEY AUTO_INCREMENT,
color_name VARCHAR(20) NOT NULL
);

Now, let’s populate them with data.

INSERT INTO sizes (size_name) VALUES ('Small'), ('Medium'), ('Large');
INSERT INTO colors (color_name) VALUES ('Red'), ('Blue');

The sizes table has 3 rows, and the colors table has 2 rows. Now, let’s perform a CROSS JOIN.

SELECT
s.size_name,
c.color_name
FROM sizes AS s
CROSS JOIN colors AS c;

The result is the Cartesian product, containing 3 * 2 = 6 rows, representing every possible combination.

size_namecolor_name
SmallRed
SmallBlue
MediumRed
MediumBlue
LargeRed
LargeBlue

Practical Applications and Performance Warnings

Section titled “Practical Applications and Performance Warnings”

While often used accidentally, CROSS JOIN has legitimate use cases:

  • Generating Data: Useful for creating comprehensive test data or populating a table with all possible combinations of attributes.
  • Reporting: In data warehousing, it can be used to create a base set of combinations (e.g., all stores vs. all dates) to which real data can then be joined.
  • Mathematical Computations: Certain complex calculations might require generating a set of all possible pairs between two datasets.

You can CROSS JOIN more than two tables. The number of rows in the result set will be the product of the number of rows in all tables. For example, if we add a fabric table with 2 types, joining sizes (3 rows), colors (2 rows), and fabric (2 rows) would produce 3 * 2 * 2 = 12 rows.

CREATE TABLE fabrics (fabric_name VARCHAR(20));
INSERT INTO fabrics VALUES ('Cotton'), ('Polyester');
SELECT
s.size_name,
c.color_name,
f.fabric_name
FROM sizes AS s
CROSS JOIN colors AS c
CROSS JOIN fabrics AS f;

This query generates all 12 possible shirt variations.

Executing a CROSS JOIN from an application is the same as any other SELECT query. Remember to handle potentially large result sets gracefully to avoid running out of memory in your application.

PHP (PDO)
Node.js (mysql2)
Java (JDBC)
Python (mysql-connector)
To perform a cross join in PHP, execute the SQL query using a secure PDO connection.
```php
<?php
// ... (use the same PDO connection setup as in previous examples)
try {
$pdo = new PDO($dsn, $user, $pass, $options);
$sql = "SELECT s.size_name, c.color_name FROM sizes AS s CROSS JOIN colors AS c ORDER BY s.size_name, c.color_name";
$stmt = $pdo->query($sql);
echo "All Product Combinations:\n";
while ($row = $stmt->fetch()) {
echo "Size: " . $row['size_name'] . ", Color: " . $row['color_name'] . "\n";
}
} catch (\PDOException $e) {
// ... (error handling)
}
?>

Use async/await and mysql2/promise to execute the query and process the results.

const mysql = require('mysql2/promise');
async function getCombinations() {
let connection;
try {
connection = await mysql.createConnection({ /* ... connection config ... */ });
const sql = 'SELECT s.size_name, c.color_name FROM sizes AS s CROSS JOIN colors AS c ORDER BY s.size_name, c.color_name';
const [rows] = await connection.execute(sql);
console.log('All Product Combinations:');
rows.forEach(row => {
console.log(`Size: ${row.size_name}, Color: ${row.color_name}`);
});
} catch (error) {
console.error('Failed to get combinations:', error);
} finally {
if (connection) await connection.end();
}
}
getCombinations();

Use a standard JDBC Statement or PreparedStatement to run the cross join query.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class CrossJoinExample {
public static void main(String[] args) {
String sql = "SELECT s.size_name, c.color_name FROM sizes AS s CROSS JOIN colors AS c ORDER BY s.size_name, c.color_name";
try (Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {
System.out.println("All Product Combinations:");
while (rs.next()) {
System.out.println(
"Size: " + rs.getString("size_name") +
", Color: " + rs.getString("color_name"));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

Use the mysql-connector-python library to execute the query and fetch the results.

import mysql.connector
config = { /* ... connection config ... */ }
try:
with mysql.connector.connect(**config) as cnx:
with cnx.cursor(dictionary=True) as cursor:
query = "SELECT s.size_name, c.color_name FROM sizes AS s CROSS JOIN colors AS c ORDER BY s.size_name, c.color_name"
cursor.execute(query)
print("All Product Combinations:")
for row in cursor.fetchall():
print(f"Size: {row['size_name']}, Color: {row['color_name']}")
except mysql.connector.Error as err:
print(err)