首页/数据/SQL 速查/GROUP BY 列序号
聚合与窗口函数54 条

GROUP BY 列序号

MySQL 与 PostgreSQL 都允许 GROUP BY 1 这类列序号写法:简短但可读性差,改 SELECT 顺序时容易改错。

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

GROUP BY 列序号是什么

按列在 SELECT 列表里的位置分组或排序,写成 GROUP BY 1、ORDER BY 2 这种形式,在聚合表达式很长时能少敲不少字。MySQL 8.0 与 PostgreSQL 都接受这种位置引用,但位置是顺序敏感的:一旦在 SELECT 里插入或调换列,同一个数字指向的列就变了,语句照样能跑通,结果却已经错位。

基本信息

支持情况MySQL 8.0 与 PostgreSQL 都支持按位置分组与排序
序号基准从 1 开始,指向 SELECT 输出列表中的列
等价写法直接写列名,或写输出列的别名
主要风险位置引用的含义随 SELECT 列顺序变化,脚本越长期越容易踩
跨库差异ORDER BY 位置多数数据库支持,GROUP BY 位置并非各家都接受

两种写法对照

维度位置写法列名写法
书写长度最短,长聚合表达式处尤其省事略长,但语义自解释
列顺序变化含义静默改变,语句不报错不受列顺序影响
评审难度要来回数 SELECT 里的列一眼能看出分组口径
重构与改名列被删除后指向另一列或直接报错改名会报错提示,容易发现漏改
跨库迁移支持情况不一致,需逐个核对基本通用

典型使用场景

  • 临场排查:手敲一次性分组统计时用序号省打字
  • 长聚合表达式:SELECT 里已是完整表达式,分组处直接写序号
  • 快速排序验证:ORDER BY 2 DESC 先看排序效果是否合理
  • 一次性脚本:不进入代码库的临时语句,风险可接受
  • 对照检查:位置写法与列名写法各跑一次,核对结果是否一致
  • 重构清单:把历史脚本里的位置引用逐个替换成列名

写法对比

写法对比
SELECT city, COUNT(*) AS cnt, SUM(amount) AS total
FROM users JOIN orders ON orders.user_id = users.id
GROUP BY 1                 # 这里的 1 指 city,列的增删都会改变它的指向
ORDER BY 2 DESC;           # 按第二列 cnt 排序

SELECT city, COUNT(*) AS cnt FROM users
GROUP BY city              # 等价写法,不怕列顺序被调整
HAVING COUNT(*) > 10;      # 聚合条件独立计算,与分组处的写法无关

SELECT city, COUNT(*) AS cnt FROM users
GROUP BY 1 HAVING cnt > 10;   # 分组用位置、条件用别名,混着写最难维护
位置写法在语法上跟常量很像,不同数据库对它的解释并不一致。把序号换成列名或输出列名,执行效果不变,但可读性、评审效率与迁移成本都会明显改善,长期留在代码库里的语句建议一律写列名。
在 SELECT 列表前面插入一列,GROUP BY 1 与 ORDER BY 2 的含义就都变了:语句能跑通,数字却对不上。改动 SELECT 列顺序之前,先搜一遍这条语句里有没有位置引用。

易错点

  • 在 SELECT 前部插入一列:位置引用指向的列随之改变,语句不报错但结果错位
  • 长期脚本沿用位置写法:重构与评审都容易漏改,维护成本被推高
  • 以为所有数据库解释一致:GROUP BY 的位置引用并非各家都接受,迁移要逐个核对
  • 分组用位置、条件用别名混写:列顺序一变,分组口径与过滤条件同时变化,排查困难

数据来源与参考

  • MySQL 8.0 Reference Manual · GROUP BY
  • PostgreSQL Documentation · GROUP BY
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌