2013-04-10 56 views
9

爲什麼這不起作用?外部查詢在內部查詢之前正在運行

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子句外部查詢第一。我如何解決這個問題?

+0

您是否自己運行內部查詢以確保它返回您期望的內容? – OldProgrammer 2013-04-10 00:52:00

+2

這很酷。我從來沒有聽說過SQL小提琴。 – anthonybell 2013-04-10 00:52:51

+0

@ OldProgrammer-是的,內部查詢工作正常。我已經嘗試過一個CTE,它也做同樣的事情。我能做到這一點的唯一方法是,如果我在'test_table'中選擇了一個成員編號,然後用該表替換子查詢。 – Lock 2013-04-10 00:56:09

回答

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優化引擎以這種方式工作(正如有人所說 - 沒有人能保證你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 
2

也許是:

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

這僅支持sql 2012,對吧? – 2013-04-10 01:11:22

+0

@EthanLi是的,但有問題沒有指定版本。 – mkjasinski 2013-04-10 01:13:28

+0

true,只是試圖說清楚 – 2013-04-10 01:16:30

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 

沒有一個優雅的解決方案,但希望這有助於

0

該評論解釋瞭如何執行計劃c (有時)選擇在like之前評估cast。一個case聲明可以幫助評估的順序,但正如亞當斯提到,即使這種方法不是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 
+1

'CASE'語句不總是短路:[Connect item](http://connect.microsoft.com/SQLServer/feedback/details/690017/case-coalesce-wont-總是評估在文本順序) – 2013-04-10 01:32:04

+0

@AdamWenger在崗位注意到。 +1 – 2013-04-10 03:52:43

+1

@AdamWenger:在文章中,它提到了一個具有集合函數的特定情況,它被指定爲首先被評估。在OP的問題中,沒有聚合函數,所以這應該不成問題。和往常一樣,測試來驗證。 – siride 2013-04-10 04:00:07

0

你可以試試這個,在執行查詢第一種情況下,如果再失敗就不會執行第2條件

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

並回答爲什麼您的查詢不起作用請檢查此explanation here