MySQL使用GROUP BY分组查询报错 ,ONLY_FULL_GROUP_BY解决方案

ysql5.7及以后默认sql_mode=“ONLY_FULL_GROUP_BY”。
含义:

sql中select后面的字段必须出现在group by后面,或者被聚合函数包裹,不然会抛出上面的错误 如以下错误:
Error Code: 1055. Expression #3 of SELECT list is not in GROUP BY clause and contains nonaggregated column ‘×××’ which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

废话就不多说了,目前整理的有以下方案:

方案1:SQL命令修改sql_mode(不建议使用)
--	1.使用select语句将sql_mode查询出来
select @@sql_mode;
-- 或者
select @@global.sql_mode;
-- 2.复制sql_mode结果,并将"ONLY_FULL_GROUP_BY"加进去,使用set或update语句更新sql_mode
set @@sql_mode =''; -- 改变已经存在的数据库sql_mode
set @@global.sql_mode=''; //改变全局配置sql_mode

这种方法是会话级别的,数据库重启后会失效。不建议在实际开发中使用。

方案2:配置文件修改sql_mode(不推荐使用)

不推荐使用的原因是,如果你不是DBA,也不是架构师,也不是领导我劝你别用,在大型项目中不可能因为你一个人菜而影响其他人的开发习惯或已有的开发规范。

Linux:

修改/etc/my.cnf文件使用编辑命令进行编辑,找到"[mysqld]“下的sql_mode,把"ONLY_FULL_GROUP_BY"j加进去并保存退出,然后使用命令"service mysqld restart"或”/etc/inint.d/mysqld restart"重启mysql服务。

windows:

修改MySQL文件下的/my.ini文件(默认安装请到C:\ProgramData\MySQL下找my.ini,自定义安装的自行查找或者百度),找到"[mysqld]"下的sql_mode,把"ONLY_FULL_GROUP_BY"j加进去,然后重启mysql服务器。不会用命令就按步骤来:我的电脑——(右键)管理——服务与应用程序——服务——MYSQL——开启(停止、重启动)。

方案3:GROUP_CONCAT()函数

使用GROUP_CONCAT()函数,语法:group_concat( [DISTINCT] 要连接的字段 [Order BY 排序字段 ASC/DESC] [Separator ‘分隔符’] ),我觉着意思就是在group by的前提下依据某个或多个字段进行排序,例如:insert_time,然后将每组排序后的某个字段进行拼接,例如:id,默认以英文","分割拼接。如果没看明白我讲的是啥,那您去百度一下吧。。。
例子:

SELECT ip, pc_name, GROUP_CONCAT( id ORDER BY collect_time DESC, insert_time DESC ) ids FROM t_sys_monitor GROUP BY ip, pc_name

结果:在这里插入图片描述
因为根据时间排序已经将需要最新一条数据id放在第一位了,所以使用SUBSTRING_INDEX(列名,截取分隔符,第几位)函数截取即可获取需要的id,然后多表关联查询得到结果。

SELECT
	t.id,
	t.ip,
	t.pc_name,
	t.status,
	t.collect_time,
	t.update_time,
	t.insert_time 
FROM
	t_sys_monitor t
	RIGHT JOIN ( SELECT SUBSTRING_INDEX( GROUP_CONCAT( id ORDER BY collect_time DESC, insert_time DESC ), ',', 1 ) id FROM t_sys_monitor GROUP BY ip, pc_name ) t1 ON t.id = t1.id 
ORDER BY
	t.collect_time DESC,
	t.insert_time DESC;
方案4:mysql8开窗函数及行号ROW_NUMBER() OVER(PARTITION BY COLUMN ORDER BY COLUMN)

1.根据ip,module分组查,collect_time倒排序查询

SELECT
	t.*,
	ROW_NUMBER() over ( PARTITION ip, module ORDER BY collet_time DESC ) rn 
FROM
	t_sys_monitor t

2.取当前行号为1的值(rn = 1)

SELECT
	m.* 
FROM
	( SELECT t.*, ROW_NUMBER() over ( PARTITION ip, module ORDER BY collet_time DESC ) rn FROM t_sys_monitor t ) m 
WHERE
	m.rn = 1
方案5:any_value()函数

待更新。。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值