视图中不应写ORDER BY,因其在嵌套查询中会被忽略,排序应由外层查询控制;GROUP BY字段须与SELECT列严格对应,MySQL严格模式下需显式处理非分组字段;物化视图支持因数据库而异,MySQL无原生支持;视图嵌套勿超三层,避免执行计划失控。

视图里别写 ORDER BY,否则用的时候会出错
MySQL 5.7+ 和 PostgreSQL 允许在视图定义里写 ORDER BY,但实际调用时往往被忽略——尤其是你再套一层 SELECT * FROM my_view WHERE ...,排序就彻底失效。SQL 标准规定:视图只是“命名的查询”,最终执行计划由外层语句决定,ORDER BY 在视图内属于无效约束。
常见错误现象:CREATE VIEW v_sales_summary AS SELECT ..., SUM(...) FROM ... GROUP BY ... ORDER BY created_date DESC,结果查出来顺序随机。
- 正确做法:把排序逻辑留在应用层或外层查询,比如
SELECT * FROM v_sales_summary ORDER BY created_date DESC - 例外场景:PostgreSQL 支持
WITH (security_barrier)视图,但排序仍不保证;SQL Server 的索引视图也不支持排序固化 - 性能影响:视图里加
ORDER BY可能误导优化器生成多余 sort 节点,尤其在嵌套视图中容易放大开销
GROUP BY 字段必须和 SELECT 列严格对应(尤其在 MySQL 严格模式下)
MySQL 默认兼容模式允许 SELECT a, b, SUM(c) FROM t GROUP BY a(b 没在 GROUP BY 里),但开启 sql_mode=STRICT_TRANS_TABLES,ONLY_FULL_GROUP_BY 后直接报错:Expression #2 of SELECT list is not in GROUP BY clause。这是对 SQL 标准的回归,也是避免隐式聚合歧义的关键防线。
- 检查当前模式:
SELECT @@sql_mode,确认含ONLY_FULL_GROUP_BY - 修复方式不是关模式,而是显式处理非分组字段:用
MAX(b)、ANY_VALUE(b)(MySQL 5.7+),或提前用子查询/CTE 拆解逻辑 - PostgreSQL 和 SQL Server 默认就强制此规则,别指望“先跑通再修”
- 报表开发中常见坑:前端传参动态拼
GROUP BY字段,但 SELECT 列没同步调整,一换维度就崩
用物化视图前先确认数据库是否真支持(别被名字骗了)
“物化视图”这个词在不同数据库里含义差很远。PostgreSQL 没原生物化视图,CREATE MATERIALIZED VIEW 是 9.3+ 才有,且刷新需手动 REFRESH MATERIALIZED VIEW;Oracle 的物化视图支持快速刷新和查询重写;而 MySQL 根本没有物化视图语法,所谓“模拟”靠的是定时 INSERT INTO summary_table SELECT ... + 应用层路由。
- 判断依据不是文档标题,而是查系统表:
SELECT * FROM pg_matviews(PG)、SELECT * FROM user_mviews(Oracle) - MySQL 用户别折腾“物化”,老实用定时任务 +
REPLACE INTO或INSERT ... ON DUPLICATE KEY UPDATE - 物化视图的代价:存储翻倍、刷新期间锁表/阻塞查询、增量刷新逻辑复杂(尤其涉及
DELETE或UPDATE) - 报表场景下更务实的选择:对高频聚合字段建覆盖索引,比物化视图启动快、维护轻
视图嵌套别超三层,否则执行计划不可控
一个报表查 v_report_final,它基于 v_sales_agg,后者又依赖 v_order_detail_clean —— 这种三层嵌套在 PostgreSQL 中可能让优化器放弃下推谓词(predicate pushdown),导致全量扫描中间结果;在 SQL Server 中还可能触发“视图展开失败”,回退成临时表操作。
- 检查方法:在查询前加
EXPLAIN(PG/MySQL)或SET SHOWPLAN_ALL ON(SQL Server),看是否出现Materialize或大体积Hash Match - 替代方案:把关键过滤条件(如日期范围、租户 ID)尽量提到最外层,用参数化视图(PG 支持
$1占位符)、或改用 CTE(WITH子句)明确控制展开时机 - 上线前必做:用真实数据量压测嵌套视图,别只在空库上验证语法
- 最容易被忽略的一点:视图权限继承是叠加的,三层嵌套意味着要给用户同时授予三个底层表的
SELECT权限,漏一个就permission denied for relation

















