为何递归查询中常采用CROSS JOIN加WHERE的写法?
WITH RECURSIVE中JOIN与CROSS JOIN+WHERE写法的对比与选择
你在查阅WITH RECURSIVE文档时遇到的两种写法:
-- 隐式CROSS JOIN + WHERE a,b WHERE (a.id=b.parent_id) -- 等价于 a CROSS JOIN b WHERE a.id=b.parent_id -- 显式JOIN a JOIN b ON (a.id=b.parent_id)
关于这两种写法的合理性、性能影响及选择建议,以下是具体分析:
1. 逻辑等价性
这两种写法在SQL逻辑上是完全等价的。a, b是SQL早期的隐式交叉连接语法,搭配WHERE子句中的连接条件,本质就是内连接(INNER JOIN);而JOIN ... ON是ANSI SQL标准的显式内连接语法,两者最终实现的是相同的数据关联逻辑。
2. 查询性能与优化器处理
现代主流数据库(如PostgreSQL、MySQL、SQL Server等)的查询优化器完全能够识别这两种写法的等价性,会将它们转换为相同的执行计划,不会因为写成CROSS JOIN+WHERE就导致效率降低。
以你提供的递归CTE示例为例,两种写法生成的执行计划是一致的——优化器会自动将隐式的交叉连接+过滤条件转换为内连接逻辑,不会先生成笛卡尔积再过滤(这是初学者容易误解的点)。即使是数据量较大的场景,优化器也会根据索引、数据分布等信息选择最优的连接策略,不受写法形式的影响。
3. 写法选择建议
优先使用显式JOIN ... ON写法
- 可读性更强:显式区分连接条件和过滤条件,逻辑更清晰,尤其是在复杂查询(多表连接、嵌套CTE)中,能避免连接逻辑和过滤逻辑混淆。
- 维护成本更低:后续开发者更容易理解关联关系,修改或扩展查询时出错概率更低。
- 符合现代SQL规范:ANSI标准的写法兼容性更好,适配不同数据库的能力更强。
选择CROSS JOIN+WHERE的场景
- 遗留代码兼容:老项目或早期文档中可能保留这种写法,为了保持代码风格一致可能会沿用。
- 个人习惯:部分开发者长期使用早期SQL语法,更习惯这种写法,但这并非必要选择。
附你的示例代码(格式化后)
CREATE TABLE body AS ( SELECT 1 id, 'body' AS name, NULL parent_id UNION ALL SELECT 2, 'head', 1 UNION ALL SELECT 3, 'eyes', 2 UNION ALL SELECT 4, 'pupils', 3 UNION ALL SELECT 5, 'torso', 1 UNION ALL SELECT 6, 'arms', 5 ); -- 使用显式JOIN WITH RECURSIVE body_paths (id, part, path) AS ( SELECT id, name, name AS path FROM body WHERE parent_id IS NULL UNION ALL SELECT body.id, body.name, CONCAT(path, '.', body.name) FROM body JOIN body_paths ON (body.parent_id=body_paths.id) ) SELECT * FROM body_paths WHERE part in ('pupils', 'arms'); -- 使用CROSS JOIN + WHERE WITH RECURSIVE body_paths (id, part, path) AS ( SELECT id, name, name AS path FROM body WHERE parent_id IS NULL UNION ALL SELECT body.id, body.name, CONCAT(path, '.', body.name) FROM body, body_paths WHERE (body.parent_id=body_paths.id) ) SELECT * FROM body_paths WHERE part in ('pupils', 'arms');
两种写法的输出结果一致:
┌────┬────────┬───────────────────────┐ │ id ┆ part ┆ path │ ╞════╪════════╪═══════════════════════╡ │ 6 ┆ arms ┆ body.torso.arms │ │ 4 ┆ pupils ┆ body.head.eyes.pupils │ └────┴────────┴───────────────────────┘
内容的提问来源于stack exchange,提问作者David542
相关产品推荐
相关产品推荐

