SQL-92和更早的版本不允许选择列表、有
条件,或命令
列表中未命名的非聚合列集团
条款。例如,这个查询在标准SQL-92中是非法的,因为非聚合的的名字
控件中未显示集团
:
SELECT o.custid, c.name, MAX(o.payment) FROM orders AS o, customers AS c WHERE o.custid = c.custid GROUP BY o.custid;
要使查询在SQL-92中是合法的,则的名字
列必须从选择列表中省略或在集团
条款。
SQL:1999及其后续版本允许每个可选特性T301都使用这种非聚合,如果它们在功能上依赖于它们的话集团
列:如果存在这样的关系的名字
和custid
,查询是合法的。举个例子,就是这样custid
的主键客户
.
MySQL实现了函数依赖的检测。如果ONLY_FULL_GROUP_BY
启用SQL模式(默认情况下),MySQL拒绝选择列表、有
条件,或命令
列表引用未被命名的非聚合列集团
在功能上也不依赖于它们。
MySQL还允许非聚合列没有在集团
条款当SQLONLY_FULL_GROUP_BY
Mode已启用,前提是此列仅限于单个值,如下例所示:
mysql> CREATE TABLE mytable (-> id INT UNSIGNED NOT NULL PRIMARY KEY, -> a VARCHAR(10), -> b INT ->);mysql> INSERT INTO mytable -> VALUES (1, 'abc', 1000), -> (2, 'abc', 2000), -> (3, 'def', 4000);mysql> SET SESSION sql_mode = sys.list_add(@@session. mode)sql_mode ONLY_FULL_GROUP_BY);mysql> SELECT a, SUM(b) FROM mytable WHERE a = 'abc';+------+--------+ | 一个|和(b ) | +------+--------+ | abc | 3000 | +------+--------+
类中也可以有多个非聚合列选择
当使用ONLY_FULL_GROUP_BY
.在本例中,每个这样的列必须限制为在哪里
所有这些限制条件必须由逻辑连接起来和
,如下所示:
mysql> DROP TABLE IF EXISTS mytable;mysql> CREATE TABLE mytable (-> id INT UNSIGNED NOT NULL PRIMARY KEY, -> a VARCHAR(10), -> b VARCHAR(10), -> c INT ->);mysql >插入mytable - >值(1、“abc”、“qrs”,1000年),- - - - - - > (2,' abc ',德国莱茵,2000),- - - - - - >(3“def”“qrs”,4000年),- - - - - - >(4“def”德国莱茵,8000),- - - - - - > (5 ' abc ' qrs, 16000), - - - - - - >(6“def”德国莱茵,32000);mysql >选择@@session.sql_mode;+---------------------------------------------------------------+ | @@ 会话。sql_mode | +---------------------------------------------------------------+ | ONLY_FULL_GROUP_BY、STRICT_TRANS_TABLES NO_ENGINE_SUBSTITUTION | +---------------------------------------------------------------+ mysql >选择a, b,和(c)从mytable - > =“abc”,b =“qrs”;+------+------+--------+ | a | | (c ) | +------+------+--------+ | abc | qrs | 17000年 | +------+------+--------+
如果ONLY_FULL_GROUP_BY
是禁用的,MySQL扩展到标准SQL使用集团
允许选择列表,有
条件,或命令
列表引用非聚合列,即使这些列在功能上不依赖集团
列。这将导致MySQL接受前面的查询。在这种情况下,服务器可以自由地从每个组中选择任何值,因此,除非它们相同,否则所选择的值是不确定的,这可能不是您想要的。此外,不能通过添加命令
条款。结果集排序发生在选择值之后,并且命令
不会影响服务器在每个组中选择的值。禁用ONLY_FULL_GROUP_BY
当您知道,由于数据的某些属性,每个非聚合列中的所有值没有在集团
对每一组都是相同的。
你可以在不禁用的情况下达到同样的效果ONLY_FULL_GROUP_BY
通过使用ANY_VALUE ()
引用非聚合列。
下面的讨论演示了函数依赖关系,当没有函数依赖关系时MySQL产生的错误消息,以及在没有函数依赖关系时导致MySQL接受查询的方法。
此查询可能无效ONLY_FULL_GROUP_BY
启用是因为非聚合地址
属性中未命名的选择列表中的列集团
条款:
SELECT name, address, MAX(age) FROM t GROUP BY name
查询在以下情况下有效的名字
主键是t
或者是独一无二的非空
列。在这种情况下,MySQL识别出所选列在功能上依赖于分组列。例如,如果的名字
是否为主键,其值决定值地址
因为每个组只有一个主键值,因此只有一行。因此,选择中没有随机性地址
值,并且不需要拒绝查询。
如果是,则查询无效的名字
不是的主键t
或一个独特的非空
列。在这种情况下,不能推断出任何函数依赖性,并会发生错误:
mysql> SELECT name, address, MAX(age) FROM t GROUP BY name;ERROR 1055 (42000): Expression #2 of SELECT list is not in GROUP BY clause and contains non - aggregated column 'mydb.t. .在GROUP BY子句中,不依赖于列的address';这与sql_mode=only_full_group_by不兼容
如果你知道,对于给定的数据集,每一个的名字
值实际上唯一地决定地址
值,地址
有效依赖于什么的名字
.要告诉MySQL接受查询,可以使用ANY_VALUE ()
功能:
SELECT name, ANY_VALUE(address), MAX(age) FROM t GROUP BY name
另外,禁用ONLY_FULL_GROUP_BY
.
然而,前面的示例非常简单。特别是,不太可能对单个主键列进行分组,因为每个组将只包含一行。有关更复杂查询中演示函数依赖关系的其他示例,请参见第12.20.4节,“功能依赖的检测”.
如果查询具有聚合函数且没有集团
子句,则在选择列表中不能有非聚合列,有
条件,或命令
列表,ONLY_FULL_GROUP_BY
启用:
mysql> SELECT name, MAX(age) FROM t;ERROR 1140 (42000): In aggregated query without GROUP BY, expression #1 of SELECT list contains nonaggregated column 'mydb.t.name';这与sql_mode=only_full_group_by不兼容
没有集团
,有一个单一的群体,它是不确定的的名字
值为该组选择。同样的,ANY_VALUE ()
可以用,如果是非物质的哪一个的名字
价值MySQL选择:
SELECT any (name), MAX(age) FROM t;
ONLY_FULL_GROUP_BY
也会影响查询的处理截然不同的
和命令
.以表为例t
有三个列c1
,c2
,c3
包含以下行:
1 . C 2 . C 3 . C 4 . C
假设我们执行下面的查询,期望结果按顺序排列c3
:
SELECT DISTINCT c1, c2 FROM t ORDER BY c3;
要对结果排序,必须先去掉重复的结果。但要这么做,我们应该保留第一行还是第三行?这种随意的选择会影响c3
,这反过来又影响了秩序,使其也变得任意。为防止此问题,可以使用具有截然不同的
和命令
是否被视为无效命令
表达式不满足以下至少一个条件:
在选择列表中,表达式等于1
表达式引用的所有属于查询所选表的列都是选择列表的元素
对标准SQL的另一个MySQL扩展允许在有
子句添加到选择列表中的别名表达式。例如,返回以下查询的名字
在表中只出现一次的值订单
:
SELECT COUNT(name) FROM orders GROUP BY name HAVING COUNT(name) = 1;
MySQL扩展允许使用别名有
合计栏条款:
SELECT COUNT(name) AS c FROM orders GROUP BY name HAVING c = 1;
标准SQL只允许列表达式集团
子句,所以这样的语句是无效的,因为地板(价值/ 100)
是非列表达式:
SELECT id, FLOOR(value/100) FROMtbl_nameGROUP BY id, FLOOR(value/100);
MySQL扩展了标准SQL,允许非列表达式集团
条款,并认为上述声明有效。
标准SQL也不允许使用别名集团
条款。MySQL扩展了标准SQL,允许使用别名,所以另一种方法写查询如下:
SELECT id, FLOOR(value/100) AS val FROMtbl_nameGROUP BY id, val;
别名瓦尔
中的列表达式集团
条款。
中存在非列表达式时集团
子句,MySQL识别出该表达式与选择列表中的表达式相等。这意味着ONLY_FULL_GROUP_BY
启用SQL模式,查询包含分组id,楼层(值/100)
因为这是一样的地板()
表达式出现在选择列表中。然而,MySQL并没有试图识别功能依赖集团
非列表达式,因此下面的查询无效ONLY_FULL_GROUP_BY
控件的一个简单公式id
列和地板()
表达的集团
条款:
SELECT id, FLOOR(value/100), id+FLOOR(value/100) FROMtbl_nameGROUP BY id, FLOOR(value/100);
解决方法是使用派生表:
SELECT id, F, id+F FROM (SELECT id, FLOOR(value/100) AS F FROMtbl_nameGROUP BY id, FLOOR(value/100)) AS dt;