【问题标题】:SQL - ORDER BY running firstSQL - ORDER BY 先运行
【发布时间】:2012-05-23 16:44:46
【问题描述】:

请查看此数据库架构:

create table Person (id int not null identity,
                     [index] varchar(30),
                     datecreated datetime, 
                     groupid int)

create table [Group] (id int identity not null, description varchar(30))

样本数据:

insert into Person ([index],datecreated,groupid) values ('4,5,6','2011-01-01',1)
insert into Person ([index],datecreated,groupid) values ('1,2,3','2011-02-02',1)
insert into Person ([index],datecreated,groupid) values ('7,8','2012-02-02',2) 

insert into [Group] (description) values ('TestGroup')
insert into [Group] (description) values ('TestGroup2')

请看下面的SQL语句:

select  *    
from Person 
inner join [Group] on Person.groupid = [group].id 
where [group].description = 'TestGroup' 
order by 
   left(substring([index], charindex(',', [index]) + 1, 200),  
        charindex(',', substring([index], charindex(',', [index]) + 1, 200)) - 1)

此 SQL 语句失败并出现以下错误:

传递给 SUBSTRING 函数的长度参数无效。

这是导致此错误的order by 子句,即它试图查找索引列的第三个元素,但第三行不存在第三个元素(只有两个元素)。

但是,我希望 [group].description = 'TestGroup' 过滤掉记录三。情况似乎并非如此。就好像order by 子句在where 子句之前运行。如果从查询中排除 order by 子句,则查询运行。

这是为什么?

【问题讨论】:

  • 为什么要在该列中存储逗号分隔值?这通常表明数据库设计非常有问题(您遇到的问题就是由此产生的结果)。
  • @a_horse_with_no_name,这是我继承的系统。它需要重新设计。
  • 你知道是什么原因导致优先考虑 GROUP BY 子句吗?
  • @marc_s,是的。看看这里,自己看看:sqlfiddle.com/#!3/29802/1

标签: sql sql-server-2005


【解决方案1】:

SQL 中的求值顺序有很弱的保证。可能首先执行排序,然后执行流聚合。这本身并没有错。

一般来说,您不能依赖执行顺序。除非在 case-expression 中,如果 SUBSTRING 的输入无效,您可以使用它在您的订单中创建像 NULL 这样的虚拟值。 案例是执行评估顺序的唯一方法。

【讨论】:

  • SQL 中的执行计划严重依赖数据和表的统计信息。它可以在没有警告或明显挑衅的情况下发生变化。
  • @JNK,有趣 - 案例似乎有很多错误。这个事实改变了我的答案:用 CASE 试试(因为文档是这样说的!)并测试它。然后希望它稍后会开始崩溃。无论如何,案例是最后的希望。
【解决方案2】:

这个 ORDER BY 非常残酷。我建议将其分解为几个查询,使用临时表或表子表达式,这样您就可以先进行过滤,和/或创建一个包含要排序的数据的列。

【讨论】:

    【解决方案3】:

    请记住,SQL 是一种声明性语言,而不是一种过程性语言。也就是说,您描述了您想要的结果集。您依赖 SQL 编译器/优化器来设置执行计划。

    通常情况下,SQL 引擎将具有一个组件,该组件从表中读取数据并执行该数据所需的所有计算。当然,这包括SELECT子句中的计算,也包括“ON”子句、“WHERE”子句和“ORDER BY”子句中的计算。

    然后引擎可以在读取数据之后进行过滤。这使引擎能够轻松地使用计算值进行过滤。

    我并不是说所有数据库都以这种方式工作。我要说的是,不能保证 SQL 语句中的操作顺序。这种情况是按错误顺序执行操作导致错误的情况之一,这会阻止 SQL 完成。您需要帮助重写查询以使其不会出现错误吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-09
      • 1970-01-01
      相关资源
      最近更新 更多