2013-04-10 28 views
9

Tại sao truy vấn này không hoạt động?Truy vấn bên ngoài đang chạy trước truy vấn bên trong

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

Xem SQL Fiddle Demo.

Các subquery nên lọc ra dữ liệu đó là không phải là số, và truy vấn bên ngoài được đúc này để một số nguyên để tôi có thể tìm kiếm bất cứ điều gì> 2.

Nó có vẻ như nó đang chạy mệnh đề where của truy vấn bên ngoài trước tiên. Làm thế nào để tôi có được điều này?

+0

Bạn có tự chạy truy vấn bên trong để đảm bảo truy vấn đó đang trả về những gì bạn mong đợi không? – OldProgrammer

+2

Thats cool. tôi chưa bao giờ nghe nói về SQL Fiddle trước đây. – anthonybell

+0

@ OldProgrammer- Vâng tôi có, và truy vấn bên trong hoạt động tốt. Tôi đã thử một CTE và nó làm điều tương tự. Cách duy nhất tôi có thể làm cho nó hoạt động là nếu tôi làm một 'số thành viên chọn thành test_table' và sau đó thay thế truy vấn phụ bằng bảng đó. – Lock

Trả lời

1

Rất thú vị, tôi đã cố gắng tái tạo điều này trên SQL Server và được tìm thấy tiếp theo. Tôi đã thay đổi truy vấn của bạn để đơn giản chỉ để đảm bảo truy vấn rằng sẽ không thất bại và tôi có thể thấy kế hoạch thực hiện:

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

kế hoạch thi công là có Bảng Scan với vị ngữ:

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

Vì vậy, điều này là do Công cụ tối ưu hóa SQL hoạt động theo cách này (như ai đó đã nói - không ai có thể đảm bảo cho bạn thứ tự của các mệnh đề ở đâu). Một trong những cách để giải quyết nó có lẽ là sử dụng IsNumeric trước

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

Có lẽ rằng:

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

chỉ được hỗ trợ bởi sql 2012, đúng không? –

+0

@EthanLi có, nhưng trong câu hỏi đã không chỉ định một phiên bản. – mkjasinski

+0

đúng, chỉ cần cố gắng làm cho nó rõ ràng –

1

Tôi có vấn đề này trước đó. Những gì tôi đã làm là:

1, bạn có thể có một cái nhìn mà làm:

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

2, hoặc bàn sử dụng tạm thời cho nó

3, hoặc sử dụng trường hợp quy định tại khoản:

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 

không có giải pháp thanh lịch, nhưng hy vọng điều này sẽ giúp

0

Nhận xét giải thích cách kế hoạch thực hiện c một (đôi khi) chọn để đánh giá số cast trước số like. Tuyên bố case có thể hỗ trợ thứ tự đánh giá nhưng như Adams đề cập đến ngay cả phương pháp này không phải là 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

câu lệnh 'CASE' không phải lúc nào cũng ngắn mạch: [Kết nối mục] (http://connect.microsoft.com/SQLServer/feedback/details/690017/case-coalesce-wont- luôn luôn đánh giá theo thứ tự văn bản) –

+0

@AdamWenger được ghi chú trong bài đăng. +1 –

+1

@AdamWenger: trong bài viết, nó đề cập đến một trường hợp cụ thể với các hàm tổng hợp, được chỉ định để luôn được đánh giá đầu tiên. Trong câu hỏi của OP, không có hàm tổng hợp, vì vậy đây không phải là vấn đề. Và, như mọi khi, kiểm tra để xác minh. – siride

0

Bạn có thể thử loại này, trong sau truy vấn điều kiện đầu tiên được thực hiện và nếu nó không thành công thì nó sẽ không thực hiện điều kiện thứ 2

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

Và để trả lời tại sao truy vấn của bạn không hoạt động, hãy kiểm tra điều này explanation here

Các vấn đề liên quan