SQL_MODE之ONLY_FULL_GROUP_BY

前言:SQL_MODE是MySQL中的一个系统变量(variable),可由多个MODE组成,每个MODE控制一种行为,在MySQL 5.7版本中默认的模式有:ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION;可使用**select @@sql_mode;**来查看自己电脑中有哪些mode;

在这里插入图片描述

本次主要讲解ONLY_FULL_GROUP_BY

ONLY_FULL_GROUP_BY

官方文档的解释:Reject queries for which the select list, HAVING condition, or ORDER BY list refer to nonaggregated columns that are neither named in the GROUP BY clause nor are functionally dependent on (uniquely determined by) GROUP BY columns.

https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_only_full_group_by

在这个模式下,我们使用分组查询时,出现在select字段后面的只能是group by后面的分组字段,或使用聚合函数包裹着的字段。请看举例:

  • 首先新建如下表(为了演示我已将mode中添加了ONLY_FULL_GROUP_BY)

在这里插入图片描述

  • 运行如下sql: __select * from product __

在这里插入图片描述

  • 运行如下sql: select * from product GROUP BY product_name,问题出现了

在这里插入图片描述

*代表全部字段,而group by 字段只有一个project_name,所以报错

  • 运行如下sql: select price,brand_name from product GROUP BY price

在这里插入图片描述

  • 运行如下sql:select price,brand_name from product GROUP BY price,brand_name,category_name

在这里插入图片描述

  • 运行如下sql:select price,brand_name from product GROUP BY brand_name,category_name,price

在这里插入图片描述

以上可以看出,当开启ONLY_FULL_GROUP_BY时,只有满足最上方条件才可以查询成功,且默认by的是离by最近的那个字段,即:

select a,b from table group by a,b,c; (正确)
select a,b,c from table group by a,b; (错误)

再看一下之前出问题的sql

SELECT
	ymv.`YEAR_MONTH` yearMonth,
	ifnull(au.total, 0) total
FROM
	year_month_view ymv
LEFT JOIN (
	SELECT
		DATE_FORMAT(au.created_at, '%Y-%m') yearMonth,
		COUNT(id) total
	FROM
		admin_user au
	WHERE
		DATE_FORMAT(au.created_at, '%Y-%m') > DATE_FORMAT(
			date_sub(curdate(), INTERVAL 12 MONTH),
			'%Y-%m'
		)
	AND is_deleted = 0
	GROUP BY
		yearMonth
) au ON ymv. `YEAR_MONTH` = au.yearMonth
GROUP BY
	ymv.`YEAR_MONTH`

因为group by 后面只有一个字段,而select后面有两个,所以会报错

  • 因此有两种修改方式
    • 第一种为补上字段,并将你希望作为分类的字段放在by的旁边
    • 第二种为修改SQL_MODE,将ONLY_FULL_GROUP_BY去掉
    • 第三种为添加any_value(field)函数
SELECT
	ymv. `YEAR_MONTH` yearMonth,
	ifnull(au.total, 0) total
FROM
	year_month_view ymv
LEFT JOIN (
	SELECT
		DATE_FORMAT(au.created_at, '%Y-%m') yearMonth,
		COUNT(id) total
	FROM
		admin_user au
	WHERE
		DATE_FORMAT(au.created_at, '%Y-%m') > DATE_FORMAT(
			date_sub(curdate(), INTERVAL 12 MONTH),
			'%Y-%m'
		)
	AND is_deleted = 0
	GROUP BY
		yearMonth
) au ON ymv. `YEAR_MONTH` = au.yearMonth
GROUP BY
	ymv.`year_month`,total

在这里插入图片描述

  • 如何修改SQL_MODE

    • 全局级别:set global sql_mode=‘ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES’;

    • 回话级别:set session sql_mode=‘ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES’;

    • 更改MySql配置文件my.ini:默认安装位置如下:C:\ProgramData\MySQL\MySQL Server x.x

在这里插入图片描述

另外,在写这篇文章中发现GROUP BY其实是有很多门道的,有兴趣可以参考官方文档

https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值