MySQL only_full_group_by详解

MySQL only_full_group_by详解

MySQL <code>only_full_group_by</code>详解” title=”MySQL <code>only_full_group_by</code>详解” /></p>
<h2>1. 什么是<code>only_full_group_by</code></h2>
<p>在MySQL中,<code>only_full_group_by</code>是一种SQL模式,它属于严格模式的一部分。这个模式要求在使用GROUP BY语句进行分组时,SELECT语句中的非聚合列必须在GROUP BY子句中出现。</p>
<p>例如,考虑以下的表<code>orders</code>:</p><div id=

order_id customer_id product_id quantity
1 001 101 10
2 001 102 20
3 002 103 15
4 002 101 5

现在,如果我们想按照customer_id分组,并计算每个客户所购买的产品数量之和,我们可以使用以下查询:

SELECT customer_id, SUM(quantity) 
FROM orders
GROUP BY customer_id;

结果将会是:

customer_id SUM(quantity)
001 30
002 20

然而,在使用only_full_group_by模式时,以上的查询将会导致错误,因为我们没有将非聚合列customer_id包含在GROUP BY子句中。

2. only_full_group_by的影响

启用only_full_group_by模式会对查询的语义有所改变。在该模式下,如果我们使用了GROUP BY子句,那么SELECT列表中除聚合函数外的列,必须在GROUP BY子句中包含。

若不遵守此规则,MySQL将返回一个错误,例如:

SELECT customer_id, SUM(quantity) 
FROM orders
GROUP BY customer_id;

在启用only_full_group_by模式时,以上的查询将会导致错误信息:
“Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column ‘orders.customer_id’ which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by”

这个错误的原因是:尽管我们想要按照customer_id进行分组,但是在SELECT列表中的customer_id没有在GROUP BY子句中包含。

3. 为什么要启用only_full_group_by

使用only_full_group_by模式可以确保查询结果的准确性。如果不启用该模式,MySQL在GROUP BY查询中的非聚合列上的处理方式是不一致的。

例如,考虑以下的表orders

order_id customer_id product_id quantity
1 001 101 10
2 001 102 20
3 002 103 15
4 002 101 5

现在,假设我们想要按照customer_id分组,并计算每个客户所购买的产品数量之和,并选取其它非聚合列product_id作为结果展示,我们可以使用以下查询:

SELECT customer_id, product_id, SUM(quantity) 
FROM orders
GROUP BY customer_id;

在没有启用only_full_group_by模式时,MySQL会在product_id列中选择一个任意的值,但实际上从语义角度讲,这是不正确的。因为在一个分组中,每个customer_id可能对应多个product_id,但是我们无法确定具体是哪个product_id。这样的查询结果是不可预测的,并且可能导致数据的不准确性。

如果启用了only_full_group_by模式,在上述的查询中将会返回错误,以提示用户进行正确的查询。这使得我们能够更加精确和准确地编写GROUP BY语句。

4. 如何启用only_full_group_by

启用only_full_group_by模式有以下几种方式:

4.1 在MySQL配置文件中设置

  1. 打开MySQL的配置文件(如my.cnfmy.ini);
  2. 找到[mysqld]段;
  3. 添加或修改sql_mode参数,添加ONLY_FULL_GROUP_BY

示例:

[mysqld]
sql_mode = "ONLY_FULL_GROUP_BY"

4.2 使用SET语句设置

可以在MySQL命令行或客户端中使用SET语句临时地修改sql_mode参数。

SET SESSION sql_mode = 'ONLY_FULL_GROUP_BY';

或者,如果您有相应的权限,也可以使用全局SET语句来修改持久性的sql_mode参数:

SET GLOBAL sql_mode = 'ONLY_FULL_GROUP_BY';

请注意,全局设置将在MySQL服务器重启后仍然有效。

4.3 在启动参数中设置

可以在启动MySQL服务器时,通过命令行参数来配置sql_mode

$ mysqld --sql_mode=ONLY_FULL_GROUP_BY

或者在my.cnf/my.ini配置文件中加入以下内容:

[mysqld]
sql_mode=ONLY_FULL_GROUP_BY

5. 示例与运行结果

考虑以下表orders

order_id customer_id product_id quantity
1 001 101 10
2 001 102 20
3 002 103 15
4 002 101 5

假设我们想要按照customer_id分组,并计算每个客户所购买的产品数量之和,并选取其它非聚合列product_id作为结果展示:

-- 查询语句1
SELECT customer_id, product_id, SUM(quantity) 
FROM orders
GROUP BY customer_id;

查询结果,当没有启用only_full_group_by时:

customer_id product_id SUM(quantity)
001 101 30
002 103 20

查询结果,当启用only_full_group_by时:

“Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column ‘orders.product_id’ which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by”

可以看到,在启用only_full_group_by模式之后,查询1将会报错,提示我们非聚合列product_id没有在GROUP BY子句中包含,从而保证了结果的准确性。

6. 总结

only_full_group_by是MySQL中的一种SQL模式,要求在使用GROUP BY语句进行分组时,SELECT语句中的非聚合列必须在GROUP BY子句中出现。启用only_full_group_by模式可以确保查询

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程