SQL如何快速汇总多源头业务数据_UNION ALL后聚合统计

2次阅读

UNION ALL 后不能直接 GROUP BY,因集合操作优先级低于 GROUP BY,须用子查询或 CTE 包裹;需注意字段对齐、类型显式转换、条件下沉、去重语义等细节。

SQL 如何快速汇总多源头业务数据_UNION ALL 后聚合统计

UNION ALL 之后不能直接 GROUP BY?先看执行顺序

SQL 中 UNION ALL 是集合操作,不是子句;它优先级低于 GROUP BY,所以写成 SELECT …… UNION ALL SELECT …… GROUP BY …… 会报错——语法不合法。真实执行流程是:先合并结果集,再对合并后的临时结果做聚合。必须用子查询或 CTE 包一层。

  • 错误写法:SELECT a FROM t1 UNION ALL SELECT a FROM t2 GROUP BY a → 报错 ERROR: syntax error at or near "GROUP"
  • 正确姿势:把 UNION ALL 整体包进子查询,外层再 GROUP BY
  • CTE 更清晰:WITH src AS (SELECT …… UNION ALL SELECT ……) SELECT ……, COUNT(*) FROM src GROUP BY ……

多源头字段对齐:NULL 和类型不一致会静默出错

业务表字段名、顺序、类型常不统一,UNION ALL 要求列数相同、对应列类型兼容。MySQL 会尝试隐式转换(比如把字符串转成数字),PostgreSQL 则更严格,类型不匹配直接报错 UNION types text and integer cannot be matched

  • 显式转类型:SELECT id::TEXT, amount FROM sales UNION ALL SELECT CAST(order_id AS TEXT), total FROM orders
  • 补缺失字段:SELECT 'sales' AS source, id, amount, NULL::TEXT AS remark FROM sales UNION ALL SELECT 'orders', order_id, total, note FROM orders
  • 别依赖 NULL 自动对齐:不同库对 NULL 类型推断不同,显式写 NULL::NUMERICNULL::VARCHAR 更稳

性能关键:加 WHERE 条件要塞进每个分支,别只在外层过滤

想统计“近 7 天订单 + 退款”,如果只在外层加 WHERE dt >= CURRENT_DATE - 7,数据库得先把所有历史数据 UNION ALL 完再过滤,IO 和内存爆炸。必须把时间条件下推到每个 SELECT 分支里。

  • 慢:WITH all_data AS (SELECT dt, amt FROM sales UNION ALL SELECT dt, amt FROM refunds) SELECT SUM(amt) FROM all_data WHERE dt >= '2024-06-01'
  • 快:SELECT dt, amt FROM sales WHERE dt >= '2024-06-01' UNION ALL SELECT dt, amt FROM refunds WHERE dt >= '2024-06-01'
  • 索引是否生效,取决于每个分支的 WHERE 是否能命中各自表的索引,别假设合并后还能用上

去重陷阱:UNION ALL ≠ UNION,但业务汇总常要“按主键去重”

UNION ALL 不去重,这是它快的原因。但业务中常遇到同一笔订单在销售表和发票表里都存在,直接 UNION ALLCOUNT(DISTINCT order_id) 可能掩盖重复计数问题。这时候得判断:到底要“记录数”还是“业务实体数”?

  • 要实体数:别靠 UNION ALL,改用 SELECT …… FROM sales FULL OUTER JOIN refunds USING (order_id) 或分步 UNION + 去重逻辑
  • 要记录数:确认各源头本身无重复(比如退款表有 status = 'success' 过滤),否则先 GROUP BY 各自源头再 UNION ALL
  • 别在 UNION ALL 后加 DISTINCT:它等价于 UNION,失去 ALL 的性能优势,且可能误杀合法重复(如不同渠道同 ID 订单)

真正卡住的往往不是语法,而是没想清楚“这个 COUNT(*) 统计的是什么”。源头语义模糊时,强行堆 UNION ALL 只会让结果越来越不可信。

星耀云
版权声明:本站原创文章,由 星耀云 2026-03-22发表,共计1657字。
转载说明:转载本网站任何内容,请按照转载方式正确书写本站原文地址。本站提供的一切软件、教程和内容信息仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。
text=ZqhQzanResources