报错信息

### Error querying database.  Cause: java.sql.SQLSyntaxErrorException: Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column ''xxx.d.brand_id'' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

这是一个典型的 MySQL ONLY_FULL_GROUP_BY 模式导致的 SQL 语法错误。

原因分析

SQL 语句中使用了 GROUP BY d.source_detail_id,但是在 SELECT 列表中包含了其他非聚合列(如 d.brand_id, d.brand_name, d.unit_id 等),而这些列并没有出现在 GROUP BY 子句中。
在 MySQL 5.7+ 版本中,默认开启了 sql_mode=ONLY_FULL_GROUP_BY。该模式要求:SELECT 列表中的每一列,要么必须包含在 GROUP BY 子句中,要么必须使用聚合函数(如 SUM, MAX, MIN, ANY_VALUE 等)进行包裹。
数据库认为,如果你只按 source_detail_id 分组,那么对于同一个 source_detail_id,如果存在多行数据且它们的 brand_id 不同,数据库就无法确定应该返回哪一行的 brand_id,因此报错。

解决办法

  1. 修改 SQL,将所有非聚合字段加入 GROUP BY;
  2. 使用 ANY_VALUE() 函数包裹非聚合列(快速修复,无需改 GROUP BY);
    如果你确定同一个 source_detail_id 下这些属性值是唯一的,或者你不在乎取哪一行的值,可以使用 MySQL 的 ANY_VALUE() 函数。这告诉数据库:“随便取一个值给我,不要报错”。
  3. 关闭 ONLY_FULL_GROUP_BY 模式;
    # 临时生效
    SET SESSION sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
    
    # 永久生效
    SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
    
    我使用的是云数据库,操作步骤是在云控制台,找到数据库实例,点击操作,选择修改参数,在参数列表中搜索 sql_mode,将 ONLY_FULL_GROUP_BY 改为空,提交参数后立即生效。

重要提示

虽然关闭 ONLY_FULL_GROUP_BY 可以快速解决你的报错,但请务必注意以下几点:

  1. 数据不确定性风险:
    关闭该模式后,MySQL 允许 SELECT 列表中出现在 GROUP BY 之外的非聚合列。如果这些列在分组后有多不同的值,MySQL 会随机返回其中一行的值。
  2. 主从同步/集群问题:
    如果你的架构包含只读实例(Read-only instances)或集群,确保所有节点的 sql_mode 配置一致,否则可能导致主从同步错误或查询结果不一致。