CROSS JOIN

This is a less commonly used join type, but still relevant. The CROSS JOIN joins every row in the left table with every row in the right table.

Suppose you have 2 tables representing types of pizza toppings, 1 for meats and 1 for cheeses.


meats
column_name type
meat
VARCHAR

cheeses
column_name type
cheese
VARCHAR

There are 2 meats available to choose from, and 3 cheeses. Suppose you can choose 1 cheese and 1 meat for your pizza. That means there are 2 · 3 = 6 possible pizza combinations to make. If you want to list all possible combinations, you can CROSS JOIN.

SELECT *
FROM meats
CROSS JOIN cheeses;
meat
VARCHAR
cheese
VARCHAR
pepperoni
mozzarella
pepperoni
provolone
pepperoni
gruyere
prosciutto
mozzarella
prosciutto
provolone
prosciutto
gruyere

Observe that every meat is joined with every cheese. In relational algebra, this type of operation is called a cartesian product. That is when you put 2 sets together to form a new set of pairs. The members of the new set are every possible pair of 1 thing from each set. I find it easier to just visualize it.

meat pepperoni prosciutto cheese mozzarella provolone gruyere

As with other joins, it generalizes to n number of joins. If you got to choose 1 meat, 2 cheeses, and a veggie, you could do something like this:

SELECT *
FROM meats
CROSS JOIN cheeses
CROSS JOIN cheeses
CROSS JOIN veggies;

However, the number of combinations grows extremely quickly.

This operation is actually quite uncommon in everyday development. Most real tables are quite large, and actual CROSS JOINs with them would be outrageously large…

…unless you limit the rows with a WHERE clause. We'll discuss that in the next section.

A CROSS JOIN Is an Inner Join

This same operation could've been done with a join type you've learned already.

SELECT *
FROM meats
JOIN cheeses
  ON TRUE;
meat
VARCHAR
cheese
VARCHAR
pepperoni
mozzarella
pepperoni
provolone
pepperoni
gruyere
prosciutto
mozzarella
prosciutto
provolone
prosciutto
gruyere

A CROSS JOIN is just an inner join without an ON clause, and we can recapitulate its behavior using JOIN by setting the on clause to ON TRUE, i.e. always match.

So if we can make an INNER JOIN act like a CROSS JOIN, can we make a CROSS JOIN act like an INNER JOIN? Yes we can. Remember this example from our app Tweeter?

SELECT
  tweeters.email,
  tweets.body,
  tweets.created_at
FROM tweeters
JOIN tweets
  ON tweeters.id = tweets.user_id
WHERE tweeters.email = 'judy14@yahoo.com';
email
VARCHAR
body
TEXT
created_at
TIMESTAMPTZ
judy14@yahoo.com
If we program the program, we can get to the THX application through the solid state USB bus!
2016-02-25 22:36:30.812+00
judy14@yahoo.com
I'll generate the optical IB bandwidth, that should application the AGP program!
2016-09-09 10:18:32.523+00
judy14@yahoo.com
generating the system won't do anything, we need to quantify the optical SQL firewall!
2021-06-16 12:42:05.054+00

You can write this as a CROSS JOIN like this:

SELECT
  tweeters.email,
  tweets.body,
  tweets.created_at
FROM tweeters
CROSS JOIN tweets
WHERE tweeters.id = tweets.user_id
  AND tweeters.email = 'judy14@yahoo.com';
email
VARCHAR
body
TEXT
created_at
TIMESTAMPTZ
judy14@yahoo.com
If we program the program, we can get to the THX application through the solid state USB bus!
2016-02-25 22:36:30.812+00
judy14@yahoo.com
I'll generate the optical IB bandwidth, that should application the AGP program!
2016-09-09 10:18:32.523+00
judy14@yahoo.com
generating the system won't do anything, we need to quantify the optical SQL firewall!
2021-06-16 12:42:05.054+00

Basically, to convert an inner join to a cross join, you can just move the ON clause condition into the WHERE clause. A WHERE clause makes the CROSS JOIN's number of rows reasonable.

It turns out that the inner join is just syntactic sugar for the cross join. In the real world, people tend to prefer to write their joins as inner joins, as the ON clause nicely separates the condition relevant for joining from the rest of the WHERE conditions.

When to Use CROSS JOIN

Since the INNER JOIN is a nicer way to write joins when there is some join condition, it only makes sense to prefer the CROSS JOIN when there is no join condition. As we've seen, the situations where you want a CROSS JOIN without any join condition are limited. However, there are some cases where it makes sense.

1. The left or right table has only 1 row.

We saw an example of this in the lesson about common table expressions. One of the CTEs had a 1-row table.

Though the official solution doesn't have it, many people would use a CROSS JOIN in the challenge Test Scores.

2. To unnest an array.

If you have a table with an array column, unnesting the array elements into separate rows and joining them with the row the original array was in is common when working with arrays.

More Syntactic Sugar

It turns out there's another equivalent way to write CROSS JOIN. You can write it as a comma-delimited list in the FROM clause.

SELECT *
FROM meats, cheeses;
meat
VARCHAR
cheese
VARCHAR
pepperoni
mozzarella
pepperoni
provolone
pepperoni
gruyere
prosciutto
mozzarella
prosciutto
provolone
prosciutto
gruyere

Whether you write it this way or with the CROSS JOIN keywords is up to personal preference.

© 2022 Andrew Carlson. All rights reserved.