Mysql WHERE子句影响结果的顺序
我对一个Mysql WHERE子句影响结果的顺序,mysql,Mysql,我对一个选择有一些奇怪的问题。 WHERE子句中的顺序是否可能影响结果 以下是我的选择: select u.userName, u.fullName, g.uuid as groupUuid, g.name as `group`, m.number as module, count(distinct b.uuid) as buildCount, max(b.datetime), count(distinct e.buildId) as errorBuildCount, e.id
选择有一些奇怪的问题。
WHERE
子句中的顺序是否可能影响结果
以下是我的选择:
select u.userName, u.fullName, g.uuid as groupUuid, g.name as `group`,
m.number as module, count(distinct b.uuid) as buildCount, max(b.datetime),
count(distinct e.buildId) as errorBuildCount, e.id as errorId
from User u
inner join GROUP_USER GU on GU.user_id = u.id
inner join `Group` g on g.id = GU.group_id
inner join Course c on c.id = g.courseId
left outer join Build b on b.userId = u.id
left outer join Module m on m.id = b.moduleId
left outer join Error e on e.buildId = b.id
where c.uuid = 'HMUUcabR1S4GRTIwt3wWxzCO' and g.uuid = 'abcdefghijklmnopqrstuvwz'
group by u.userName,m.number,c.uuid, g.uuid
order by g.id asc, u.fullName asc, m.number asc
选择u.userName、u.fullName、g.uuid作为groupUuid、g.name作为'group`,
m、 编号作为模块,计数(不同的b.uuid)作为构建计数,最大值(b.datetime),
计数(不同的e.buildId)为errorBuildCount,e.id为errorId
来自用户u
内部联接组\u用户GU on GU.USER\u id=u.id
g.id=GU.Group\U id上的内部联接'Group'g
c.id=g.courseId上的内部连接层c
在b.userId=u.id上左外部联接构建b
m.id=b.moduleId上的左外连接模块m
e.buildId=b.id上的左外部联接错误e
其中c.uuid='hmuucar1s4grtiwt3wwxzco'和g.uuid='abcdefghijklmnopqrstuvz'
按u.userName、m.number、c.uuid、g.uuid分组
按g.id asc、u.fullName asc、m.number asc订购
这将重现此结果:
当我使用此条件时:
其中g.uuid='abcdefghijklmnopqrstuvwz'和c.uuid='hmuucar1s4grtiwt3wwxzco'
(不同的顺序)我得到不同的结果(请参见errorId
列):
你能帮帮我吗?整个选择是错误的,还是可能是一个mysql
bug?结果之间的唯一区别是errorId
列。sql标准(sql-92标准,签出)不允许未分组和未聚合的列,并且在大多数db引擎中都不会运行。因此,在这种情况下,引擎的行为未指定。根据(由于):
MySQL扩展了GROUPBY的使用,因此select列表可以引用GROUPBY子句中未命名的未聚合列。这意味着前面的查询在MySQL中是合法的。您可以使用此功能通过避免不必要的列排序和分组来获得更好的性能。但是,这主要是在GROUP BY中未命名的每个未聚合列中的所有值对于每个组都相同时才有用。服务器可以从每个组中自由选择任何值,因此,除非它们相同,否则选择的值是不确定的
您可以将errorId
作为聚合值获取:
MAX(e.id) as errorId
或者将其包括在分组依据列表中:
group by u.userName,m.number,c.uuid, g.uuid,e.Id
那么您的查询结果应该是稳定的
进一步阅读:
-详细解释sql标准和mysql实现之间的差异。(多亏了)结果之间的唯一区别是errorId
列。sql标准(sql-92标准,签出)不允许未分组和未聚合的列,并且在大多数db引擎中都不会运行。因此,在这种情况下,引擎的行为未指定。根据(由于):
MySQL扩展了GROUPBY的使用,因此select列表可以引用GROUPBY子句中未命名的未聚合列。这意味着前面的查询在MySQL中是合法的。您可以使用此功能通过避免不必要的列排序和分组来获得更好的性能。但是,这主要是在GROUP BY中未命名的每个未聚合列中的所有值对于每个组都相同时才有用。服务器可以从每个组中自由选择任何值,因此,除非它们相同,否则选择的值是不确定的
您可以将errorId
作为聚合值获取:
MAX(e.id) as errorId
或者将其包括在分组依据列表中:
group by u.userName,m.number,c.uuid, g.uuid,e.Id
那么您的查询结果应该是稳定的
进一步阅读:
-详细解释sql标准和mysql实现之间的差异。(多亏了)您的代码中有两个不同的连接树,基本上是:
user
/ \
group_user build
/ \
group module
| |
course error
这种构造会导致未定义的结果,特别是当一个分支中的联接结果与另一个分支中的匹配记录数不同时。MySQL必须尝试填补缺失的部分,并进行猜测。更改WHERE
子句的顺序可以并且将更改完整结果,因为您正在更改mysql猜测的方式。您的代码中有两个不同的连接树,本质上是:
user
/ \
group_user build
/ \
group module
| |
course error
这种构造会导致未定义的结果,特别是当一个分支中的联接结果与另一个分支中的匹配记录数不同时。MySQL必须尝试填补缺失的部分,并进行猜测。更改WHERE
子句的顺序可以并且将更改完整结果,因为您正在更改mysql猜测的方式。在聚合之前按所有列分组。最佳实践……在大多数情况下。而且很可能会扭曲你的答案…在聚合之前按所有列分组。最佳实践……在大多数情况下。而且很可能会扭曲您的答案…所以这两个屏幕标题之间的唯一区别是一个errorID,其中一个是9
,另一个是NULL
?可能您的基础数据在两个查询之间发生了变化。where
子句中的顺序不会影响结果。这可能是因为在SELECT
中有多个列不在GROUP BY
中。虽然MySQL允许这样做(其他RDBMS不允许),但它通常会导致非分组列的意外行为(不确定的结果)。我将在错误e
上重新检查您的联接。因此,这两个屏幕封口之间的唯一区别是一个errorID,其中一个是9
,另一个是NULL
?可能您的基础数据在两个查询之间发生了更改。where
子句中的顺序不会影响结果。这可能是因为在SELECT
中有多个列不在GROUP BY
中。虽然MySQL允许这样做(其他RDBMS不允许),但它通常会导致非分组列的意外行为(结果不确定)。我会在错误e
上重新检查您的连接。不要删除