Error related to only_full_group_by when executing a query in MySql

前端 未结 18 2451
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-21 04:39

I have upgraded my system and have installed MySql 5.7.9 with php for a web application I am working on. I have a query that is dynamically created, and when run in older ve

相关标签:
18条回答
  • 2020-11-21 04:47

    I will try to explain you what this error is about.
    Starting from MySQL 5.7.5, option ONLY_FULL_GROUP_BY is enabled by default.
    Thus, according to standart SQL92 and earlier:

    does not permit 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

    (read more in docs)

    So, for example:

    SELECT * FROM `users` GROUP BY `name`;
    

    You will get error message after executing query above.

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

    Why?
    Because MySQL dont exactly understand, what certain values from grouped records to retrieve, and this is the point.

    I.E. lets say you have this records in your users table:

    And you will execute invalid query showen above.
    And you will get error shown above, because, there is 3 records with name John, and it is nice, but, all of them have different email field values.
    So, MySQL simply don't understand which of them to return in resulting grouped record.

    You can fix this issue, by simply changing your query like this:

    SELECT `name` FROM `users` GROUP BY `name`
    

    Also, you may want to add more fields to SELECT section, but you cant do that, if they are not aggregated, but there is crutch you could use (but highly not reccomended):

    SELECT ANY_VALUE(`id`), ANY_VALUE(`email`), `name` FROM `users` GROUP BY `name`
    

    Now, you may ask, why using ANY_VALUE is highly not recommended?
    Because MySQL don't exactly know what value of grouped records to retrieve, and by using this function, you asking it to fetch any of them (in this case, email of first record with name = John was fetched).
    Exactly I cant come up with any ideas on why you would want this behaviour to exist.

    Please, if you dont understand me, read more about how grouping in MySQL works, it is very simple.

    And by the end, here is one more simple, yet valid query.
    If you want to query total users count according to available ages, you may want to write down this query

    SELECT `age`, COUNT(`age`) FROM `users` GROUP BY `age`;
    

    Which is fully valid, according to MySQL rules.
    And so on.

    It is important to understand what exactly the problem is and only then write down the solution.

    0 讨论(0)
  • 2020-11-21 04:48

    Go to mysql or phpmyadmin and select database then simply execute this query and it will work. Its working fine for me.

    SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
    
    0 讨论(0)
  • 2020-11-21 04:51

    Use ANY_VALUE() to refer to the nonaggregated column.

    SELECT name,           address , MAX(age) FROM t GROUP BY name; -- fails
    SELECT name, ANY_VALUE(address), MAX(age) FROM t GROUP BY name; -- works
    

    From MySQL 5.7 docs:

    You can achieve the same effect without disabling ONLY_FULL_GROUP_BY by using ANY_VALUE() to refer to the nonaggregated column.

    ...

    This query might be invalid with ONLY_FULL_GROUP_BY enabled because the nonaggregated address column in the select list is not named in the GROUP BY clause:

    SELECT name, address, MAX(age) FROM t GROUP BY name;
    

    ...

    If you know that, for a given data set, each name value in fact uniquely determines the address value, address is effectively functionally dependent on name. To tell MySQL to accept the query, you can use the ANY_VALUE() function:

    SELECT name, ANY_VALUE(address), MAX(age) FROM t GROUP BY name;
    
    0 讨论(0)
  • 2020-11-21 04:51

    This is what helped me to understand the entire issue:

    1. https://stackoverflow.com/a/20074634/1066234
    2. https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html

    And in the following another example of a problematic query.

    Problematic:

    SELECT COUNT(*) as attempts, SUM(elapsed) as elapsedtotal, userid, timestamp, questionid, answerid, SUM(correct) as correct, elapsed, ipaddress FROM `gameplay`
                            WHERE timestamp >= DATE_SUB(NOW(), INTERVAL 1 DAY)
                            AND cookieid = #
    

    Solved by adding this to the end:

      GROUP BY timestamp, userid, cookieid, questionid, answerid, elapsed, ipaddress
    

    Note: See the error message in PHP, it tells you where the problem lies.

    Example:

    MySQL query error 1140: In aggregated query without GROUP BY, expression #4 of SELECT list contains nonaggregated column 'db.gameplay.timestamp'; this is incompatible with sql_mode=only_full_group_by - Query: SELECT COUNT(*) as attempts, SUM(elapsed) as elapsedtotal, userid, timestamp, questionid, answerid, SUM(correct) as correct, elapsed, ipaddress FROM gameplay WHERE timestamp >= DATE_SUB(NOW(), INTERVAL 1 DAY) AND userid = 1

    In this case, expression #4 was missing in the GROUP BY.

    0 讨论(0)
  • 2020-11-21 04:52

    I had to edit the below file on my Ubuntu 18.04:

    /etc/mysql/mysql.conf.d/mysqld.cnf

    with

    sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
    

    and

    sudo service mysql restart

    0 讨论(0)
  • 2020-11-21 04:53

    If you are using wamp 3.0.6 or any upper version other than the stable 2.5 you might face this issue, firstly the issue is with sql . you have to name the fields accordingly. but there is another way by which you can solve it. click on green icon of wamp. mysql->mysql settings-> sql_mode->none. or from console you can change the default values.

    mysql> set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
    mysql> set session sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
    
    0 讨论(0)
提交回复
热议问题