外部查询在内部查询之前运行

时间:2013-04-10 00:42:15

标签: sql sql-server tsql

为什么这不起作用?

select *
from
(
    select membership_number
    from members
    where membership_number not like '%[^0-9]%'
) mem
where cast(membership_number as int) > 2

请参阅SQL Fiddle Demo

子查询应该过滤掉非数字的数据,外部查询将其转换为整数,以便我可以查找任何> 2。

好像它首先运行外部查询的where子句。我该如何解决这个问题?

5 个答案:

答案 0 :(得分:2)

也许那样:

select *
from
(
    select
        membership_number
    from
        members
    where
        membership_number not like '%[^0-9]%'
) mem
where Try_Convert(int, membership_number) > 2

答案 1 :(得分:1)

我以前遇到过这个问题。我做的是:

1,你可以有一个视图:

select membership_number
    from members
    where membership_number not like '%[^0-9]%'

2,或使用临时表

3,或用例子句:

select *
from
(
    select membership_number
    from members
    where membership_number not like '%[^0-9]%'
) mem
where (CASE WHEN ISNUMERIC(membership_number) THEN cast(membership_number as int) ELSE 0 END) > 2

没有一个优雅的解决方案,但希望这有帮助

答案 2 :(得分:1)

非常有趣,我试图在SQL Server上重现这个,然后找到它。我将您的查询更改为简单只是为了确保查询不会失败,我可以看到执行计划:

select *
from
(
    select membership_number
    from members
    where membership_number not like '%[^0-9]%'
) mem
where membership_number > '2'

执行计划是带有谓词的表扫描:

[master].[dbo].[members].[membership_number]>'2' 
    AND NOT [master].[dbo].[members].[membership_number] like '%[^0-9]%'

所以这是因为SQL Optimization引擎以这种方式工作(正如有人所说 - 没有人可以保证where子句的顺序)。修复它的方法之一可能是在

之前使用ISNUMERIC
select *
from
(
    select membership_number
    from members
    where membership_number not like '%[^0-9]%'
) mem
where ISNUMERIC(mem.membership_number) = 1 and cast(mem.membership_number as int) > 2

答案 3 :(得分:0)

评论解释了执行计划如何(有时)选择评估cast之前的likecase声明可以帮助评估顺序,但正如亚当斯提到的那样,即使这种方法也不是100%。

select  *
from    members
where   case
            when membership_number like '%[^0-9]%' then 0
            when cast(membership_number as int) > 2 then 1
            else 0
        end = 1

答案 4 :(得分:0)

你可以试试这个,在下面的查询中执行第一个条件,如果失败那么它就不会执行第二个条件

select
    membership_number
  from
    members
where 
isnumeric(membership_number) = 1 and 
cast(membership_number as int) > 2

要回答为什么您的查询无效,请查看此explanation here