直接拼多个GROUP BY查询用UNION ALL会报错,因列数、顺序、类型必须严格对齐;需显式补位(如NULL::TEXT)、加标识字段(如'by_dept')、外层套GROUP BY才能真合并。

直接用 UNION ALL 拼多个 GROUP BY 查询,90% 的情况会报错——不是语法问题,而是结果集结构不匹配。
UNION ALL 前必须手动对齐字段数量、顺序和类型
数据库不会自动补列、转类型或重命名。比如一个查 dept, COUNT(*),另一个查 region, SUM(sales), AVG(price),直接 UNION ALL 必然触发 ERROR 1222 或 ORA-01789。
- 每个子查询的
SELECT列数必须完全一致,多一列少一列都不行 - 对应位置的列类型要兼容:别让
INT和DATE并排,MySQL 可能全转成字符串,后续SUM()就失效 - 用
NULL::TEXT(PostgreSQL)或CAST(NULL AS VARCHAR)(SQL Server / MySQL)显式占位,别依赖隐式转换 - 第一个子查询的列名决定最终结果集字段名,后面子查询里的
AS alias全被忽略
加标识字段区分来源,否则结果不可读
拼完一堆 COUNT(*) 和 SUM(amount) 放在同一列里,根本分不清哪行是按部门统计的、哪行是按地区统计的。
- 在每个子查询里加一个常量字段,如
'by_dept' AS source、'by_region' AS source - 别用数字 1/2/3,业务含义模糊;也别用中文空格或特殊符号,容易在 BI 工具里出编码问题
- 这个字段最好放在最左边或最右边,方便肉眼快速识别,不影响主指标对齐
真合并得套一层外层 GROUP BY,不是拼完就完事
如果目标是“把不同口径的原始数据合并后,再统一按某个维度汇总”,比如合并昨日订单+上周订单,再按 product_id 算总销量,那必须先 UNION ALL 再 GROUP BY。
- 写法是:
SELECT product_id, SUM(quantity) FROM (SELECT ... UNION ALL SELECT ...) t GROUP BY product_id - 反过来——各自
GROUP BY后再拼——只会得到一堆独立聚合行,无法跨源叠加 - 注意
NULL值:若某张表里product_id IS NULL,拼进去后所有NULL会被归为同一组,业务上是否允许这样合并,得提前确认
ORDER BY 和 LIMIT 只能在最外层生效
UNION ALL 是操作符,不是语句块,子查询里写 ORDER BY 或 LIMIT 会直接报错(除非配了窗口函数或 OFFSET)。
- 想取“每组 top 3”?
UNION ALL本身做不到,得用ROW_NUMBER() OVER (PARTITION BY ...)包裹整个合并结果 - 需要全局排序导出?只能在最终
SELECT后加ORDER BY,且不能带子查询别名(如t.sort_col),要用实际字段名 - MySQL 默认给
UNION结果加临时表排序,不需要时加ORDER BY NULL可省开销
最容易被跳过的其实是类型对齐细节:同一个指标列,在不同子查询里用了 COUNT(*)、AVG()、MAX(),不显式 CAST 到统一精度,后期参与计算或导出到 Excel 时可能无声截断或溢出。

















