当前位置: 首页 > 知识库问答 >
问题:

WHERE子句的顺序影响结果

慕祯
2023-03-14

我对一个< code>select有一些奇怪的问题。< code>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

这将重现这个结果:http://dl.dropbox.com/u/4892450/sqlSelectProblem/select1.PNG

当我使用这个条件时:

其中 g.uuid = 'abcdefghijklmnopqrstuvwz' 和 c.uuid = 'HMUUcabR1S4GRTIwt3wWxzCO' (不同的顺序) 我得到一个不同的结果(参见 errorId 列): http://dl.dropbox.com/u/4892450/sqlSelectProblem/select2.PNG

你能帮我一下吗?是整个select都错了,还是可能是< code>mysql的bug?

共有3个答案

宗政唯
2023-03-14

聚合前按所有列分组。最佳实践...大多数情况下。很有可能会扭曲你的答案...

樊宏义
2023-03-14

代码中有两个不同的连接树,本质上:

               user
              /    \
    group_user      build
       /              \
    group             module
       |               |
    course           error

这种构造会导致未定义的结果,特别是如果一个分支中的联接结果具有与另一个分支不同的匹配记录数。MySQL必须尝试填补缺失的部分,并进行猜测。更改<code>WHERE</code>子句的顺序可以并将改变完整的结果,因为您改变了mysql进行猜测的方式。

慕容明煦
2023-03-14

结果之间的唯一区别是 errorId 列。sql 标准(sql-92 标准,请查看链接)不允许未分组和未聚合的列,甚至不会在大多数数据库引擎中运行。因此,未指定引擎在此情况下的行为。Accoding to docs(感谢Marcus Adams):

MySQL扩展了GROUP BY的使用,以便选择列表可以引用未在GROUP BY子句中命名的非聚合列。这意味着前面的查询在MySQL中是合法的。您可以使用此功能通过避免不必要的列排序和分组来获得更好的性能。但是,这主要适用于每个非聚合列中未在 GROUP BY 中命名的所有值对于每个组都相同的情况。服务器可以从每个组中自由选择任何值,因此除非它们相同,否则所选的值是不确定的。

您可以将< code>errorId作为一个聚合值:

MAX(e.id) as errorId

或将其包含在“分组依据”列表中:

group by u.userName,m.number,c.uuid, g.uuid,e.Id

那么你的查询结果应该是稳定的。

进一步阅读:

为什么MySQL添加与SQL标准冲突的功能?- 详细解释sql标准和mysql实现之间的差异。(感谢GarethD)

 类似资料:
  • 问题内容: 假设我有一个漫长而昂贵的查询,里面挤满了条件,搜索了大量的行。我还有一个特殊条件,例如公司ID,它将限制需要大量搜索的行数,将其范围从数十万缩小到几十。 我这样做是否会对MySQL性能产生任何影响: 或这个: 问题答案: 不,顺序应该不会有太大的不同。当发现哪些行与条件匹配时,将针对每一行检查整个条件(通过布尔逻辑组合的所有子条件)。 一些智能数据库引擎将尝试猜测条件的哪些部分可以更快

  • 问题内容: 我在表中有两个索引字段- 和(单个索引,不是复合索引)。 的字段值非常有限(假设它仅为0或1),因此50%的表记录具有相同的。另一方面,值来自更大的集合,因此具有相同值的记录量很小。 这些查询中的任何一个都会比另一个查询运行得更快吗? 另外,如果两个字段都没有索引,是否会改变行为? 问题答案: SQL被设计为一种声明性语言,而不是一种过程性语言。因此,查询优化器应该 不会 考虑在决定如

  • 请看以下三个查询。我无法理解计算结果为TRUE的条件在附加到where子句时如何不返回行。我希望在第二个查询中得到User1,因为第一个查询显示条件的计算结果为TRUE。

  • 如果我们有一个由col、col2、col3分区的配置单元表,那么在对该表执行SELECT时,如果我想在WHERE子句中指定这些列,它们是否必须以相同的顺序出现,以便利用分区?我的意思是,逻辑上是的,但无论我以什么顺序指定它们,HIVE编译器都不能理解它们的实际顺序。它应该能够在内部应用正确的顺序,因为HIVE已经知道正确的顺序是col2、col2、col3,所以它以这种方式使用它。HIVE在我们定

  • 本章提供了有关如何使用JDBC应用程序从表中选择记录的示例。 这将在从表中选择记录时使用WHERE子句添加其他条件。 在执行以下示例之前,请确保您具备以下示例 - 要执行以下示例,您可以使用实际用户名和密码替换用户名和密码。 您的MySQL或您正在使用的任何数据库已启动并正在运行。 所需的步骤 (Required Steps) 使用JDBC应用程序创建新数据库需要以下步骤 - Import the

  • SQL Server 2008 我有一个有许多行的视图,在那里也可以有精确的行多次。我已经尝试将ROW_NUMBER()作为row_id(按col1排序),但遇到问题: 编辑:我添加了一个例子,应该在发帖之前就做了。 没有WHERE子句: 选择ROW_NUMBER()OVER(按col1排序)作为row_id,RESULT.* FROM ( 选择“Adam”col1,“West”col2 全部联合