Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error related to only_full_group_by when executing a query in MySql

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 versions of MySql it works fine. Since upgrading to 5.7 I get this error:

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

Note the Manual page for Mysql 5.7 on the topic of Server SQL Modes.

This is the query that is giving me trouble:

SELECT mod_users_groups.group_id AS 'value',         group_name AS 'text'  FROM mod_users_groups LEFT JOIN mod_users_data ON mod_users_groups.group_id = mod_users_data.group_id  WHERE  mod_users_groups.active = 1    AND mod_users_groups.department_id = 1    AND mod_users_groups.manage_work_orders = 1    AND group_name != 'root'    AND group_name != 'superuser'  GROUP BY group_name  HAVING COUNT(`user_id`) > 0  ORDER BY group_name 

I did some googling on the issue, but I don't understand only_full_group_by enough to figure out what I need to do to fix the query. Can I just turn off the only_full_group_by option, or is there something else I need to do?

Let me know if you need more information.

like image 554
Dan Bemowski Avatar asked Dec 06 '15 07:12

Dan Bemowski


People also ask

What is ONLY_FULL_GROUP_BY in MySQL?

If ONLY_FULL_GROUP_BY is disabled, a MySQL extension to the standard SQL use of GROUP BY permits the select list, HAVING condition, or ORDER BY list to refer to nonaggregated columns even if the columns are not functionally dependent on GROUP BY columns. This causes MySQL to accept the preceding query.

What is non aggregated column MySQL?

If the ONLY_FULL_GROUP_BY SQL mode is enabled (which it is by default), MySQL rejects 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 them.

How do I disable ONLY_FULL_GROUP_BY in MySQL?

To disable ONLY_FULL_GROUP_BY in MySQL, remove ONLY_FULL_GROUP_BY from the sql-mode setting in the MySQL configuration file, /etc/my. cnf . This file can only be modified via SSH as the root user or WHM >> Terminal. ONLY_FULL_GROUP_BY cannot be disabled for a single account or database.

How do I permanently change SQL mode in MySQL?

If you are using Windows Operating System, check your directory my. cnf or my. ini file. sql_mode="TRADITIONAL".


2 Answers

I would just add group_id to the GROUP BY.

When SELECTing a column that is not part of the GROUP BY there could be multiple values for that column within the groups, but there will only be space for a single value in the results. So, the database usually needs to be told exactly how to make those multiple values into one value. Commonly, this is done with an aggregate function like COUNT(), SUM(), MAX() etc... I say usually because most other popular database systems insist on this. However, in MySQL prior to version 5.7 the default behaviour has been more forgiving because it will not complain and then arbitrarily choose any value! It also has an ANY_VALUE() function that could be used as another solution to this question if you really needed the same behaviour as before. This flexibility comes at a cost because it is non-deterministic, so I would not recommend it unless you have a very good reason for needing it. MySQL are now turning on the only_full_group_by setting by default for good reasons, so it's best to get used to it and make your queries comply with it.

So why my simple answer above? I've made a couple of assumptions:

1) the group_id is unique. Seems reasonable, it is an 'ID' after all.

2) the group_name is also unique. This may not be such a reasonable assumption. If this is not the case and you have some duplicate group_names and you then follow my advice to add group_id to the GROUP BY, you may find that you now get more results than before because the groups with the same name will now have separate rows in the results. To me, this would be better than having these duplicate groups hidden because the database has quietly selected a value arbitrarily!

It's also good practice to qualify all the columns with their table name or alias when there's more than one table involved...

SELECT    g.group_id AS 'value',    g.group_name AS 'text'  FROM mod_users_groups g LEFT JOIN mod_users_data d ON g.group_id = d.group_id  WHERE g.active = 1    AND g.department_id = 1    AND g.manage_work_orders = 1    AND g.group_name != 'root'    AND g.group_name != 'superuser'  GROUP BY    g.group_name,    g.group_id  HAVING COUNT(d.user_id) > 0  ORDER BY g.group_name 
like image 81
davmos Avatar answered Sep 29 '22 06:09

davmos


You can try to disable the only_full_group_by setting by executing the following:

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'; 

MySQL 8 does not accept NO_AUTO_CREATE_USER so that needs to be removed.

like image 26
WeiYuan Avatar answered Sep 29 '22 04:09

WeiYuan