You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

为何在视图中使用无转换过滤的CTE?两种SQL写法的疑问

关于CTE包裹简单UNION ALL写法的合理性分析

这个问题挺实用的,我来聊聊两种写法的差异以及教授可能的考量点:

首先要明确一个核心事实:在现代主流数据库(比如PostgreSQL 12+、MySQL 8+、SQL Server、Oracle)中,这两种写法会被查询优化器处理成完全相同的执行计划,性能上没有任何区别——你的同事提到的“数据加载到RAM中更快”其实是个误解,简单的CTE在这些数据库里会被优化器“展开”,和直接写UNION ALL的逻辑完全一致,不会有额外的内存加载优势。

那教授这么教可能有这些合理依据:

  • 教学的扩展性思维:教授大概率是从「代码可维护性」和「未来扩展」的角度出发。现在的场景只是简单的SELECT *,但如果之后需要给TableA加过滤条件、给TableB加字段转换或窗口函数,用CTE的结构可以直接在对应的CTE块里修改,不用动UNION ALL的核心逻辑。比如:

    CREATE VIEW myview AS
    WITH CTE AS (
      SELECT id, name, create_date FROM tableA WHERE create_date > '2023-01-01'
    ), CTE2 AS (
      SELECT id, name, create_date FROM TableB WHERE status = 'active'
    )
    SELECT * FROM CTE UNION ALL SELECT * FROM CTE2;
    

    这种写法的模块化结构,对于新手来说更容易养成良好的代码组织习惯,应对复杂场景时更顺手。

  • 语义可读性提升:即使当前场景很简单,CTE的命名(当然实际项目里应该用更有意义的名字,比如ActiveTableA)能明确区分每个数据源的逻辑模块。阅读代码的人一眼就能知道每个CTE对应的数据集,比直接写一堆SELECT * FROM ... UNION ALL的语义更清晰——教授可能是在培养开发者的「代码可读性」意识。

  • 历史或特定场景的遗留习惯:如果教授是在较早的时期学习的数据库,某些老版本的数据库(比如PostgreSQL 11及以前)对复杂CTE的处理是“物化”的(即真的把CTE结果存到临时内存/磁盘),但这种简单包裹的CTE依然会被优化器展开。不过这个理由在现在已经不成立了。

总结一下:在你当前的简单场景下,你的写法更简洁,完全没问题。教授的教法不是针对这个特定场景的性能优化,而是在传递「模块化代码组织」「面向未来扩展」的编程思维——这也是专业开发者需要养成的习惯哦。

内容的提问来源于stack exchange,提问作者Henrov

火山引擎 最新活动