SQL - 首先运行ORDER BY

时间:2012-05-23 16:44:46

标签: sql sql-server-2005

请查看此数据库架构:

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子句,即它正在尝试查找索引列的第三个元素,但第3行不存在于第3行(只有两个元素)。

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

这是为什么?

3 个答案:

答案 0 :(得分:0)

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

一般情况下,您不能依赖执行顺序。除了case-expression之外,如果NULL的输入无效,您可以使用它来创建订单中SUBSTRING之类的虚拟值。 案例是执行评估订单的唯一方法。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

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

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

我不是说所有数据库都以这种方式工作。我所说的是,不能保证SQL语句中的操作顺序。这种情况是以错误的顺序执行操作导致错误的情况之一,这会阻止SQL完成。您是否希望帮助重写查询,以便它不会收到错误?