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:any_value()函式
待更新。。。