CROSS JOIN 与笛卡尔积
了解如何有意使用交叉连接生成组合,以及意外交叉连接为何会导致行数暴增
CROSS JOIN 与笛卡尔积 是 CoddyKit 上的免费 SQL Interview Prep 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 SQL Interview Prep 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 SQL Interview Prep 课程共包含 4 节课。
面试官用来设陷阱的 JOIN
CROSS JOIN 会将左表的每一行与右表的每一行配对。它没有 ON 条件。如果表 A 有 4 行,表 B 有 3 行,那么结果就有 4 x 3 = 12 行。
这称为笛卡尔积。面试官会询问它,原因有两个:一是检验您是否能够有意生成组合,二是看您能否识别出会导致结果集爆炸式增长的意外交叉连接。
显式 CROSS JOIN 语法
现代且易读的笛卡尔积写法,是使用显式的 CROSS JOIN 关键字。请注意,这里没有 ON 子句,这会向代码审查者清楚地表明您的意图。
这里我们将每种尺寸与每种颜色配对,以构建完整的产品矩阵。
SELECT s.size, c.color
FROM sizes s
CROSS JOIN colors c;旧式逗号语法
您仍然会看到有人在 FROM 子句中使用逗号来写笛卡尔积,并且不指定连接条件。这是传统的 ANSI 语法。
它产生的结果与 CROSS JOIN 完全相同,但这种写法很危险:如果您原本打算添加连接条件却忘记了,数据库不会报错,而是悄悄执行交叉连接。请优先使用显式的 CROSS JOIN。
-- Same result as CROSS JOIN, but easy to write by accident
SELECT s.size, c.color
FROM sizes s, colors c;示例:构建尺寸表
假设一家商店销售 3 种尺寸和 4 种颜色的 T 恤,并且希望为每种可能的款式都生成一行,即使其中一些款式尚未备货。一次交叉连接就能生成全部 12 种组合。
这是最常见的有意使用场景:生成完整的选项网格。
SELECT s.size, c.color, 0 AS stock_qty
FROM sizes s
CROSS JOIN colors c
ORDER BY s.size, c.color;生成日历网格
这是 CROSS JOIN 在面试中的另一个经典用途:构建一个密集网格,确保每种组合都存在,即使某些数据缺失。
这里我们将每家商店与每个日期进行组合,随后对销售数据执行 LEFT JOIN,从而为每家商店每天生成一行,并用零填补缺失值。交叉连接可以确保没有任何商店日期组合被跳过。
SELECT st.store_id, d.day
FROM stores st
CROSS JOIN calendar d
WHERE d.day BETWEEN DATE '2024-01-01' AND DATE '2024-01-31';意外的笛卡尔积爆炸
面试官会重点考察的危险点是:您连接了两张表,却忘记了连接条件。数据库不会报错,而是很乐意返回所有组合。
如果 orders 有 100,000 行,而 customers 有 50,000 行,结果就会有 50 亿行。查询会长时间无响应,内存会耗尽,数值也会严重膨胀。在代码审查中能够识别出这种模式,是一个积极信号。
-- BUG: no join condition between the two tables
SELECT o.order_id, c.name
FROM orders o, customers c;
-- returns COUNT(orders) * COUNT(customers) rows如何发现意外的交叉连接
面试官希望您指出以下症状:
- 行数大致等于两张表大小的乘积,而不是它们的和。
SUM等聚合结果按某个固定倍数膨胀。- 查询计划显示没有连接筛选条件的嵌套循环。
解决方法几乎总是:在两张表之间补上缺失的 ON 或 WHERE 等值条件。
CROSS JOIN 与 ON 始终为真的 INNER JOIN
CROSS JOIN 在逻辑上等同于 INNER JOIN ... ON 1=1。两者都会生成完整的笛卡尔积。
实际上,INNER JOIN 就是在交叉连接之后,再根据 ON 条件进行筛选。这一思维模型可以解释为什么缺失条件会使 INNER JOIN 退化为 CROSS JOIN。
-- These two queries return identical results
SELECT * FROM a CROSS JOIN b;
SELECT * FROM a INNER JOIN b ON 1 = 1;与数字表进行交叉连接
一个很实用的技巧是:有意与小型的 numbers 或 generate_series 表进行交叉连接,以扩展行数。例如,可以将一行中的数量转换为多个代表单个单位的行。
这里通过连接一个序列,并保留不超过数量的数字,让每个产品行重复 qty 次。
SELECT p.product_id, n.n AS unit_number
FROM products p
CROSS JOIN generate_series(1, 100) AS n(n)
WHERE n.n <= p.qty;性能与安全实践
由于输出会成倍增长,绝不要对两张大型表执行交叉连接。至少应确保其中一侧很小,例如尺寸列表、小型日历或数字表。
在面试中,请明确说明这一点:“只有当一侧很小且有明确上限时,CROSS JOIN 才是安全的;否则结果将难以管理。” 这句话体现的是判断力,而不只是对语法的了解。
何时使用 CROSS JOIN
当您需要两个集合的每一种组合时,请有意使用 CROSS JOIN:
- 生成选项矩阵(尺寸 × 颜色)。
- 在执行 LEFT JOIN 之前补齐时间序列(商店 × 日期)。
- 通过数字表扩展行。
如果您不需要每一种组合,那么您几乎肯定应该使用带有 ON 条件的连接。
快速检查
测试您对笛卡尔积的理解。
要点回顾:CROSS JOIN
要点回顾:
- CROSS JOIN 会将左侧的每一行与右侧的每一行配对;输出大小是输入行数的乘积。
- 不带条件的逗号语法会产生相同的笛卡尔积,而且经常是意外造成的。
- 请有意将它用于组合网格、时间序列补齐,以及通过数字表扩展行。
- 缺失
ON条件的 INNER JOIN 会悄悄退化为交叉连接,形成面试官很喜欢考察的爆炸问题。
常见问题解答
「CROSS JOIN 与笛卡尔积」课时是免费的吗?
是的 — 「CROSS JOIN 与笛卡尔积」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 SQL Interview Prep 课程的其余内容,请升级到 CoddyKit PRO。 SQL Interview Prep 课程共包含 4 节课。
「CROSS JOIN 与笛卡尔积」这节课中我会学到什么?
了解如何有意使用交叉连接生成组合,以及意外交叉连接为何会导致行数暴增 你通过在浏览器中直接运行的动手代码来练习 SQL Interview Prep,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 SQL Interview Prep 需要有经验吗?
无需任何先前经验。CoddyKit 上的 SQL Interview Prep 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「CROSS JOIN 与笛卡尔积」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 SQL Interview Prep 课中编写并运行代码吗?
能。每节 SQL Interview Prep 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- CROSS JOIN 与笛卡尔积
- 使用 SELF JOIN 处理层级关系
- 比较同一表中的行
- 选择正确的连接类型