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
上重新检查您的连接。不要删除