MySQL Error: SELECT list is not in GROUP BY clause
MySQL Error: SELECT list is not in GROUP BY clause
我的查询有问题,mysql 抛出以下错误:
#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
查询是:
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;
当您使用 GROUP BY 时,您可以在 select-list 中使用表达式,前提是它们每组只有一个值。否则你会得到不明确的查询结果。
对于您的情况,MySQL 认为 s.status
每个组可能有多个值。例如,您按 p.products_id
分组,但 s.status
是另一个 table specials
中的列,可能与 table 存在一对多关系products
。因此 specials
中可能有多行具有相同的 products_id
,但 status
的值不同。如果是这样,查询应该使用 status
的哪个值?模棱两可。
在您的数据中,您可能碰巧限制了行,这样 products
中的每一行在 specials
中只有一行。但是 MySQL 不能做出这样的假设。
MySQL 5.6 及更早版本允许您编写此类模棱两可的查询,相信您知道自己在做什么。但是 MySQL 5.7 默认启用更严格的强制执行(这可以像早期版本一样不那么严格)。
解决方法是遵循以下规则:select 列表中的每一列都必须属于以下三种情况之一:
- 该列位于 COUNT()、SUM()、MIN、MAX()、AVERAGE() 或 GROUP_CONCAT() 等聚合函数内。
- 该列是
GROUP BY
子句中指定的列之一。
- 该列在功能上依赖于
GROUP BY
子句中指定的列。
如需更多解释,请阅读这篇优秀的博客:Debunking GROUP BY myths
关于你的评论,我只能猜测,因为你还没有发布你的 table 定义。
我猜测 products_description
和 manufacturers
在功能上依赖于 products
,因此可以将它们列在 select 列表中。但是这个假设可能不正确,我不知道你的架构。
无论如何,关于s.status
的错误应该通过使用聚合函数来解决。我以 MAX()
为例。
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;
我还以正确的方式重写了您的联接。应避免逗号式连接。
您要尝试 ORDER BY
吗? GROUP BY
子句尝试为 GROUP BY
子句中列中的每个不同值 return 一行,除非您向该子句添加更多列。抛出错误是因为您有其他未包含在子句中的非聚合列 - 聚合列类似于 MAX(p.products_id)
或 SUM(p.products_price)
。在您的查询中,有多行具有相同的 p.product_price 和不同的 s.status 值,因此 GROUP BY
没有意义。
MySQL 分组处理:https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html
聚合函数:http://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html
如果您想在特定列上使用 GROUP BY 并获取结果的 ID,有一个很好的技巧可以做到这一点:
SELECT `distinct_column`, MAX(`id`), MAX(`another_int_column`) FROM `table_name` GROUP BY `distinct_column`
结果:
distinct_column id another_int_column
Abertamy 13579 11
Adamov 17765 14
Adolfovice 2924 3
Achotín 2241 2
Babice 17772 14
现在您有来自 distinct_column 的不同值以及相应行的值。
source
我认为 id 和 another_int_column 必须是唯一的,但我不确定。
不知道为什么没有人强调对 s.status 列使用 ANY_VALUE() 内置函数。
看看这个: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
我的查询有问题,mysql 抛出以下错误:
#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
查询是:
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;
当您使用 GROUP BY 时,您可以在 select-list 中使用表达式,前提是它们每组只有一个值。否则你会得到不明确的查询结果。
对于您的情况,MySQL 认为 s.status
每个组可能有多个值。例如,您按 p.products_id
分组,但 s.status
是另一个 table specials
中的列,可能与 table 存在一对多关系products
。因此 specials
中可能有多行具有相同的 products_id
,但 status
的值不同。如果是这样,查询应该使用 status
的哪个值?模棱两可。
在您的数据中,您可能碰巧限制了行,这样 products
中的每一行在 specials
中只有一行。但是 MySQL 不能做出这样的假设。
MySQL 5.6 及更早版本允许您编写此类模棱两可的查询,相信您知道自己在做什么。但是 MySQL 5.7 默认启用更严格的强制执行(这可以像早期版本一样不那么严格)。
解决方法是遵循以下规则:select 列表中的每一列都必须属于以下三种情况之一:
- 该列位于 COUNT()、SUM()、MIN、MAX()、AVERAGE() 或 GROUP_CONCAT() 等聚合函数内。
- 该列是
GROUP BY
子句中指定的列之一。 - 该列在功能上依赖于
GROUP BY
子句中指定的列。
如需更多解释,请阅读这篇优秀的博客:Debunking GROUP BY myths
关于你的评论,我只能猜测,因为你还没有发布你的 table 定义。
我猜测 products_description
和 manufacturers
在功能上依赖于 products
,因此可以将它们列在 select 列表中。但是这个假设可能不正确,我不知道你的架构。
无论如何,关于s.status
的错误应该通过使用聚合函数来解决。我以 MAX()
为例。
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;
我还以正确的方式重写了您的联接。应避免逗号式连接。
您要尝试 ORDER BY
吗? GROUP BY
子句尝试为 GROUP BY
子句中列中的每个不同值 return 一行,除非您向该子句添加更多列。抛出错误是因为您有其他未包含在子句中的非聚合列 - 聚合列类似于 MAX(p.products_id)
或 SUM(p.products_price)
。在您的查询中,有多行具有相同的 p.product_price 和不同的 s.status 值,因此 GROUP BY
没有意义。
MySQL 分组处理:https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html 聚合函数:http://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html
如果您想在特定列上使用 GROUP BY 并获取结果的 ID,有一个很好的技巧可以做到这一点:
SELECT `distinct_column`, MAX(`id`), MAX(`another_int_column`) FROM `table_name` GROUP BY `distinct_column`
结果:
distinct_column id another_int_column
Abertamy 13579 11
Adamov 17765 14
Adolfovice 2924 3
Achotín 2241 2
Babice 17772 14
现在您有来自 distinct_column 的不同值以及相应行的值。
source
我认为 id 和 another_int_column 必须是唯一的,但我不确定。
不知道为什么没有人强调对 s.status 列使用 ANY_VALUE() 内置函数。
看看这个: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