Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggre

原文連接:https://blog.csdn.net/hq091117/article/details/79065199mysql

https://blog.csdn.net/allen_tsang/article/details/54892046sql

MySQL 5.7.5後only_full_group_by成爲sql_mode的默認選項之一,這可能致使一些sql語句失效。vim

好比下表game:函數

 

id group_id name score
1 A 小剛 20
2 B 小明 19
3 B 小花 17
4 C 小紅 18

執行sql:
select name, group_id from game group by group_id(記爲sql_make_group)
返回:this

Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'game.name' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

解決方法

  1. 把group by字段group_id設成primary key 或者 unique NOT NULL。這個方法在實際操做中沒什麼意義。搜索引擎

  2. 使用函數any_value把報錯的字段name包含起來。如,select any_value(name), group_id from game group by group_idspa

  3. 在配置文件my.cnf中關閉sql_mode=ONLY_FULL_GROUP_BY.。msqyl的默認配置是sql_mode=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。能夠把ONLY_FULL_GROUP_BY去掉,也能夠去掉全部選項設置成sql_mode=,若是你確信其餘選項不會形成影響的話。.net

成功的步驟:命令行

命令行打開mysql.cnf,能夠用whereis查找rest

sudo vim /etc/mysql/conf.d/mysql.cnf

滾動到文件底部複製並粘貼

[mysqld] 
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

wq保存並退出

重啓MySQL 

sudo service mysql restart

執行成功後,返回結果應該是

name group_id
小剛 A
小明 B
小紅 C

爲何默認設置ONLY_FULL_GROUP_BY限制?

對於上述的報錯信息,個人理解是select字段裏包含了沒有被group by條件惟一肯定的字段name。

由於執行sql_make_group語句實際上把兩行紀錄小明小花合併成一行,搜索引擎不知道該返回哪一條,因此認爲這樣的sql是武斷的(arbitrary).

解決辦法2和3都是禁止檢查返回結果的惟一性。

進階討論

上述辦法能夠解決報錯的問題,但也說明sql語句自己有邏輯問題。name字段不該該出如今返回結果,由於它是不肯定的。

考慮這樣的需求:按group_id分組後,找出每組得分最少的人。

執行sql: select any_value(name) as name, group_id, min(score) as score from game group by group_id order by min(score)

返回結果

name group_id score
小明 B 17
小紅 C 18
小剛 A 20

B組的name小明(由於小明的id更小),而指望結果應該是小花

因此單純使用group by沒法實現這樣的需求。可使用臨時表的方法:

select id, name,t.group_id, t.score from (select group_id, min(score) as score from game group by group_id order by min(score)) t inner join game on t.group_id=game.group_id and t.score=game.score

相關文章
相關標籤/搜索