CROSS JOIN 是什么
CROSS JOIN 把两张表无条件配对,结果行数是两边行数的乘积。它有两种完全不同的用途:主动生成组合集(尺码 × 颜色、日期 × 门店),用来补全报表里应当为 0 的行;以及被误用——多表查询漏写连接条件,结果集瞬间膨胀。MySQL 里 CROSS JOIN 带 ON 会被当作内连接处理,PostgreSQL 保持严格的笛卡尔积语义,写 INNER JOIN … ON 更不容易产生歧义。
基本信息
| 结果行数 | 左表行数 × 右表行数 |
|---|---|
| 等价写法 | FROM a, b(不带连接条件时的隐式交叉连接) |
| MySQL 细节 | CROSS JOIN 带 ON 条件时按内连接处理 |
| PostgreSQL | 严格保持笛卡尔积语义,需要条件时改写为 INNER JOIN … ON |
| 规模风险 | 两张大表交叉会产生海量行,聚合指标随之失真 |
典型使用场景
- 生成维度组合骨架:尺码 × 颜色、日期 × 门店
- 补全报表零值行:骨架与事实表 LEFT JOIN 后用 COALESCE 补 0
- 构造测试数据:把两个小维度交叉得到用例组合
- 交叉分析:小维度之间的两两比对
- 排查多表查询漏写连接条件导致的行数膨胀
主动使用:组合骨架
主动使用:组合骨架
-- 生成 尺码 × 颜色 的组合集
SELECT s.size, c.color
FROM sizes s
CROSS JOIN colors c
ORDER BY s.size, c.color;
-- 日期 × 门店 骨架,再左连接真实销量,补出零值行
SELECT d.d, sh.id AS shop_id, COALESCE(t.amount, 0) AS amount
FROM (SELECT DISTINCT stat_date AS d FROM daily_stats) d
CROSS JOIN shops sh
LEFT JOIN daily_stats t
ON t.stat_date = d.d AND t.shop_id = sh.id
ORDER BY d.d, sh.id;使用要点与风险
| 要点 | 说明 | 风险 |
|---|---|---|
| 行数 | 等于两边行数的乘积 | 大表之间交叉会瞬间产生海量行 |
| 组合骨架 | 适合几十到几百行的小维度表 | 明细表参与时必须先去重 |
| 补零值 | 配合 LEFT JOIN 与 COALESCE 使用 | 要确认业务上确实存在「应为 0」的行 |
| 误用 | 多表查询漏写连接条件 | 结果膨胀且往往不报错,很难察觉 |
生成组合骨架时两边都应是去重后的小维度集合;如果其中一边是明细表,先按维度去重再交叉,否则骨架本身已经膨胀,后续连接与聚合都会变慢。
两表都忘写连接条件时结果按乘积增长(1000 × 1000 即百万行),生产查询上线前务必核对实际返回行数与 EXPLAIN 估算行数是否匹配。