两表UNION结果分组随机返回行的原因及仅用UNION优先取表1数据方案
现象原因
- 你的数据库关闭了
ONLY_FULL_GROUP_BYSQL模式,触发了MySQL等数据库的非标准GROUP BY扩展行为:当GROUP BY指定的字段没有覆盖SELECT子句中所有非聚合字段时,数据库不会抛出语法错误,而是会从分组内的多行数据里随机返回某一行的非聚合字段值,没有固定优先级。 - 你的UNION结果中两行的
Date、C字段值完全一致,外层查询按这两个字段分组后,B属于非分组非聚合字段,因此数据库会随机从两行中选一行返回,就是你看到的随机返回结果的问题。
另外你原SQL的表1子查询存在逻辑错误:你按带时分秒的A字段分组,但SELECT返回的是Date(A),会导致单日数据返回多条时分秒不同的行,外层GROUP BY后才会合并,属于冗余逻辑。
解决方案(仅用UNION,不使用JOIN)
核心思路是给两个来源的数据增加优先级标记,让表1数据优先级高于表2,分组时优先取优先级高的行的数据即可。
修改后的SQL如下:
SELECT `Date`, B, C FROM ( -- 表1数据设置高优先级1 SELECT DATE(A) AS `Date`, SUM(B) AS B, C, 1 AS priority FROM TABLE1 WHERE DATE(A) = '2021-01-01' AND C = 20 GROUP BY DATE(A), C -- 修正原分组逻辑,按日期维度分组 UNION ALL -- 改用UNION_ALL跳过不必要的去重校验,提升性能 -- 表2数据设置低优先级2 SELECT A AS `Date`, SUM(B) AS B, C, 2 AS priority FROM TABLE2 WHERE A = '2021-01-01' AND C = 20 GROUP BY A, C -- 按优先级升序排序,表1数据始终排在同分组最前面 ORDER BY priority ASC ) AS d GROUP BY d.`Date`, d.C;
逻辑说明
- 新增的
priority字段用来标记数据来源优先级,表1优先级1高于表2的2 - 内层查询按优先级排序后,表1数据始终排在同一分组的最前面,数据库GROUP BY时会稳定返回排在最前面的行的字段值,实现表1有数据时优先返回表1结果的需求
- 如果表1没有对应日期的匹配数据,内层查询就只有表2的行,自然返回表2的结果,符合业务要求。
内容的提问来源于stack exchange,提问作者ero35353535
相关产品推荐
相关产品推荐

