首页/数据/数据库速查/CROSS JOIN 与 SELF JOIN
SQL 语法52 条

CROSS JOIN 与 SELF JOIN

CROSS JOIN 是无条件笛卡尔积(慎用);SELF JOIN 是同一张表自连接,常用于层级与前后行比较。

数据库速查数据更新于 2026-10-13

CROSS JOIN 与 SELF JOIN 是什么

CROSS JOIN 是无条件连接,结果行数等于左右两侧行数的乘积,也就是笛卡尔积;它正确的用法是「有意识地做排列组合」,比如两三个小集合拼枚举,而不是漏写条件的连接。SELF JOIN 是自连接:同一张表起两个别名互相连接,用来比较同表内的不同行,比如层级关系、前后行差值。

基本信息

适用版本MySQL 5.7 / 8.0
结果行数CROSS JOIN = 左表行数 × 右表行数
语义等价CROSS JOIN 与 FROM a, b 完全相同,只是显式写法更清楚
自连接要点同一张表必须起两个不同别名
典型风险误用 CROSS JOIN 产生千万级中间结果

典型使用场景

  • 生成数字或日期序列:两个小集合 CROSS JOIN 得到枚举值,配合函数拼出日历
  • 报表的维度组合:按「渠道 × 品类」补全空格子,保证输出每个组合都有行
  • 同表相邻行比较:本行与上一行做差,得出增量或环比
  • 层级展开:员工-上级、分类-父分类这类自引用结构逐层查询
  • 压力测试造数据:小数据量 CROSS JOIN 快速放大成测试数据集

自连接比较相邻行

自连接比较相邻行
-- 本行与上一行做差,得到每个指标的增量
SELECT a.id, a.value - b.value AS delta
FROM metrics a
JOIN metrics b ON b.id = a.id - 1
WHERE a.id > 1        # 去掉第一条没有前序行的记录
ORDER BY a.id;

生成数字序列(小型 CROSS JOIN)

生成数字序列(小型 CROSS JOIN)
-- 10 × 3 = 30 个组合,得到 1 到 30 的序列
SELECT d1.n + d2.n * 10 + 1 AS seq
FROM (SELECT 0 AS n UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
      UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) d1
CROSS JOIN (SELECT 0 AS n UNION SELECT 1 UNION SELECT 2) d2
ORDER BY seq;

连接类型对照

写法结果何时用
INNER JOIN ... ON只保留匹配行常规关联,最常用
LEFT JOIN ... ON保留左表全部行补全缺失维度、找未匹配记录
CROSS JOIN左右全组合枚举组合,必须显式且规模可控
FROM a, b等同于 CROSS JOIN老写法,容易漏条件,建议改显式
CROSS JOIN 一旦作用在两张大表上,中间结果会瞬间撑爆临时表与磁盘;线上执行前先用 COUNT(*) 估算两侧行数,或加 LIMIT 试跑,确认计划里没有出现巨量 rows 估算。

易错点

  • 漏写连接条件退化成笛卡尔积:百万行乘百万行,磁盘临时表写满、实例 IO 打满
  • 自连接大表却没有索引:每行都要对全表扫描一次,成本随行数平方增长
  • 自连接两处写同一别名:报 Not unique table/alias,语句直接失败
  • 用 CROSS JOIN 生成序列时行数算错:少一层或乘数写错,得到的枚举范围偏小却不易察觉
  • 把 CROSS JOIN 当隐式内连接用(在外层 WHERE 补条件):可读性差且优化器计划不稳定,容易在重构时踩坑

数据来源与参考

  • MySQL 8.0 Reference Manual: JOIN Clause

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌