報錯信息
Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'database.table.column' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
翻譯過來就是在group by 的地方有一些列是沒有包括進去的
具體問題具體分析,我這里的問題是:select 的時候使用了TIMESTAMPDIFF 中的兩個列名並沒有包括在group by 中
mysql 5.7以后的版本數據庫的默認模式設置成了
only_full_group_by模式,而在執行的sql里有一些重復的行group by 的時候mysql 不知道選擇哪一個行
錯誤實例
1:
SELECT
ifnull( sum( checkTime ) / count( 1 ), 0 ) AS time
FROM
( SELECT TIMESTAMPDIFF( MINUTE, CreateTime, EndTime ) AS checkTime FROM statistics_report WHERE AND ReportStatus = 2 GROUP BY reportid ) a
2:
SELECT ifnull( sum( treatmentTime ) / count( 1 ), 0 ) AS time FROM ( SELECT TIMESTAMPDIFF( MINUTE, min( CreateTime ), max( EndTime ) ) AS treatmentTime FROM statistics_report WHERE CreateTime > ? SartTime AND CreateTime < ? EndTime AND IsReportOperate = 2 AND createtime <> endtime GROUP BY reportid ) a
解決方案:
1:使用any_value() 包括具體提示的列名,使mysql 不再糾結與具體哪一個列
2: 把sql_mode 改成非only_full_group_by模式(如果是剛開發項目,且 ,對於項目有深入了解后 ,進行可行性分析后 再改,一般不建議,)
3:把sql 優化 ,對於每一個分組的元素 清晰的告知mysql 需要怎么選擇
成功的寫法:
1:
SELECT ifnull( sum( checkTime ) / count( 1 ), 0 ) AS time FROM ( SELECT TIMESTAMPDIFF( MINUTE, CreateTime, EndTime ) AS checkTime, reportid FROM statistics_report WHERE ReportStatus = 2 ) a GROUP BY reportid
-- 這里只是將group by 移動到了括號外面,在括號內不分組,在括號外進行分組,checkTime用sum函數來取值,解決問題。
2:
SELECT ifnull( sum( timestampdiff( MINUTE, starttime, endtime ) ) / count( 1 ), 0 ) AS time FROM ( SELECT min( createtime ) starttime, max( endtime ) endtime, reportid FROM statistics_report WHERE CreateTime > ? SartTime AND CreateTime < ? EndTime AND IsReportOperate = 2 AND createtime <> endtime GROUP BY reportid ) a
-- 這里是將timestampdiff 於min max 分開,在進行取最大最小值的時候group by ;在timestampdiff 的時候 不需要分組 ,因為這時候reportid 沒有重復的。
-- 另外這里加了ifnull 是為了取到數據的時候避免null
結束分析:
group by 的問題 很奇怪的點在於 5.7 的mysql 版本改版;bug出現具有偶發性;在mysql client執行不抱錯,而在程序中執行會報錯;
這是哪個問題導致了問題的復雜性,在了解問題原理后 從根本上解決是最直接的方案。
時常問問自己:是不是太菜。
