4

I have a problem with my query and mysql throws the following error:

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

Query is:

select   p.*,
pd.*,
m.*,
IF(s.status, s.specials_new_products_price, null) as specials_new_products_price,
IF(s.status, s.specials_new_products_price, p.products_price) as final_price
FROM products p 
LEFT JOIN specials s ON p.products_id = s.products_id  
LEFT JOIN manufacturers m using(manufacturers_id) , 
          products_description pd,
          categories c,
          products_to_categories p2c
WHERE p.products_view = 1  
AND p.products_status = 1
AND p.products_archive = 0
AND c.virtual_categories = 0
AND p.products_id = pd.products_id
AND p.products_id = p2c.products_id
AND p2c.categories_id = c.categories_id
AND pd.language_id = 1

GROUP BY p.products_id;
0

4 Answers 4

17

When you use GROUP BY, you can use expressions in your select-list only if they have a single value per group. Otherwise you get ambiguous query results.

In your case, MySQL believes that s.status might have multiple values per group. For example, you're grouping by p.products_id but s.status is a column in another table specials, perhaps in a one-to-many relationship with table products. So there might be multiple rows in specials with the same products_id, but different values for status. If that's the case, which value for status should the query use? It's ambiguous.

In your data, you might happen to limit the rows such that you only have one row in specials for each row in products. But MySQL can't make that assumption.

MySQL 5.6 and earlier let you write such ambiguous queries, trusting that you know what you're doing. But MySQL 5.7 enables more strict enforcement by default (this can be made less strict to behave like earlier versions).

The fix is to follow this rule: Every column in your select-list must fall into one of three cases:

  • The column is inside an aggregate function like COUNT(), SUM(), MIN, MAX(), AVERAGE(), or GROUP_CONCAT().
  • The column is one of the column(s) named in the GROUP BY clause.
  • The column is functionally dependent on the column(s) named in the GROUP BY clause.

For more explanation read this excellent blog: Debunking GROUP BY myths


Re your comment, I can only make a guess because you have not posted your table definitions.

I'm guessing that products_description and manufacturers are functionally dependent on products, so it's okay to list them as is in the select-list. But this assumption may not be correct, I don't know your schema.

Anyway, the error about s.status should be resolved by using an aggregate function. I'm using MAX() as an example.

SELECT p.*,
pd.*,
m.*,
MAX(IF(s.status, s.specials_new_products_price, NULL)) 
  AS specials_new_products_price,
MAX(IF(s.status, s.specials_new_products_price, p.products_price)) 
  AS final_price
FROM products p 
LEFT OUTER JOIN specials s ON p.products_id = s.products_id  
INNER JOIN manufacturers m ON p.manufacturers_id = m.manufacturers_id
INNER JOIN products_description pd ON p.products_id = pd.products_id
INNER JOIN products_to_categories p2c ON p.products_id = p2c.products_id
INNER JOIN categories c ON p2c.categories_id = c.categories_id
WHERE p.products_view = 1  
AND p.products_status = 1
AND p.products_archive = 0
AND c.virtual_categories = 0
AND pd.language_id = 1
GROUP BY p.products_id;

I also rewrote your joins in the proper way. Comma-style joins should be avoided.

3
  • 1
    Beat me to it! Great explanation as well. Commented Aug 1, 2016 at 18:30
  • I tried differents way like select SQL_CALC_FOUND_ROWS s.products_id, or select SQL_CALC_FOUND_ROWS count(p.products_id) but no solution Any idea to rewrite this ?
    – kurama
    Commented Aug 1, 2016 at 20:39
  • @kurama you are trying to aggregate the column you're grouping by. As Bill described, you need to make sure that the other columns included in the select list are included the GROUP BY clause, or they are aggregated, or are otherwise dependent on a grouped column so that the grouping works properly. For example, select p.products_id, s.status, sum(p.products_price), ... from products p group by p.products_id, s.status Commented Aug 1, 2016 at 21:43
1

Are you trying to do an ORDER BY? The GROUP BY clause attempts to return one row for each distinct value in the column in the GROUP BY clause, unless you add more columns to the clause. The error is being thrown because you have other non-aggregated columns that are not being included in the clause - aggregated columns would be something like MAX(p.products_id) or SUM(p.products_price). In your query, there are multiple rows with the same p.product_price and different s.status values, so the GROUP BY isn't meaningful.

MySQL Group By handling: https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html Aggregate functions: http://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html

0
0

If you want to use GROUP BY on specific column and get the id's of the results there is one nice trick how to do it:

SELECT `distinct_column`, MAX(`id`), MAX(`another_int_column`) FROM `table_name` GROUP BY `distinct_column`

Result:

distinct_column  id       another_int_column
Abertamy         13579    11
Adamov           17765    14
Adolfovice       2924     3
Achotín          2241     2
Babice           17772    14

Now you have distinct values from distinct_column and with it the values of the corresponding row.

source

I think that the id and another_int_column have to be unique, but i'm not sure.

0

Not sure why no one emphasizing using ANY_VALUE() inbuilt function for the s.status column.

Check this out: https://dev.mysql.com/doc/refman/8.0/en/group-by-handling.html https://dev.mysql.com/doc/refman/8.0/en/miscellaneous-functions.html#function_any-value

Not the answer you're looking for? Browse other questions tagged or ask your own question.