2013-09-05 103 views
39

Tôi đang tạo truy vấn SQL trong đó tôi cần điều khoản where có điều kiện.Điều khoản WHERE có điều kiện trong SQL Server

Nó phải là một cái gì đó như thế này:

SELECT 
    DateAppr, 
    TimeAppr, 
    TAT, 
    LaserLTR, 
    Permit, 
    LtrPrinter, 
    JobName, 
    JobNumber, 
    JobDesc, 
    ActQty, 
    (ActQty-LtrPrinted) AS L, 
    (ActQty-QtyInserted) AS M, 
    ((ActQty-LtrPrinted)-(ActQty-QtyInserted)) AS N 
FROM 
    [test].[dbo].[MM] 
WHERE 
    DateDropped = 0 
      --This is where i need the conditional clause 
    AND CASE 
      WHEN @JobsOnHold = 1 THEN DateAppr >= 0 
      ELSE DateAppr != 0 
     END 

Các truy vấn trên không hoạt động. Đây không phải là cú pháp chính xác hay có cách nào khác để làm điều này mà tôi không biết?

Tôi không muốn sử dụng SQL động, vì vậy có cách nào khác hoặc tôi phải sử dụng giải pháp thay thế như sử dụng if else và sử dụng cùng một truy vấn với các mệnh đề khác nhau where?

+0

Thay đổi câu hỏi hoặc mã (từ 'DateAppr = 0' thành' DateAppr> = 0') sau khi đã trả lời ... Tại sao? –

+0

Xin lỗi! Tôi quên rằng ở nơi đầu tiên vì vậy chỉ cần sửa chữa nó –

Trả lời

52

Hãy thử điều này

SELECT 
    DateAppr, 
    TimeAppr, 
    TAT, 
    LaserLTR, 
    Permit, 
    LtrPrinter, 
    JobName, 
    JobNumber, 
    JobDesc, 
    ActQty, 
    (ActQty-LtrPrinted) AS L, 
    (ActQty-QtyInserted) AS M, 
    ((ActQty-LtrPrinted)-(ActQty-QtyInserted)) AS N 
FROM 
    [test].[dbo].[MM] 
WHERE 
    DateDropped = 0 
    AND (
    (ISNULL(@JobsOnHold, 0) = 1 AND DateAppr >= 0) 
    OR 
    (ISNULL(@JobsOnHold, 0) != 1 AND DateAppr != 0) 
    ) 

You can read more about conditional WHERE here.

+3

Khi bảng của bạn phát triển, bạn sẽ muốn xem hiệu suất của truy vấn mà bạn kết thúc, bởi vì trình tối ưu hóa có thể trở thành khá không hài lòng với các loại truy vấn này. – GaTechThomas

7

Vấn đề với truy vấn của bạn là ở các biểu thức THENELSE phải có biểu thức đánh giá một số hoặc varchar hoặc bất kỳ kiểu dữ liệu nào khác nhưng không theo giá trị boolean.

Bạn chỉ cần sử dụng logic boolean (hay đúng hơn là logic ternary rằng SQL sử dụng) và viết lại nó:

WHERE 
    DateDropped = 0 
AND (@JobsOnHold = 1 AND DateAppr >= 0 
    OR (@JobsOnHold <> 1 OR @JobsOnHold IS NULL) AND DateAppr <> 0 
    ) 
+0

Tôi nhầm lẫn chỉnh sửa bài viết của bạn. Lấy làm tiếc. – Devart

+0

Cảm ơn. Điều này là tốt! –

+1

Chỉ cần một truy vấn Theo [link] này (http://dba.stackexchange.com/a/5337/27862) câu trả lời có thể có trường hợp khi cả hai điều kiện sẽ được giải quyết trong sử dụng toán tử AND vì vậy nếu lần đầu tiên không thành công thì cũng nó có thể áp dụng điều kiện DateAppr = 0 phải không? –

21

Hãy thử điều này một -

WHERE DateDropped = 0 
    AND (
     (ISNULL(@JobsOnHold, 0) = 1 AND DateAppr >= 0) 
     OR 
     (ISNULL(@JobsOnHold, 0) != 1 AND DateAppr != 0) 
    ) 
+0

Cảm ơn. Điều này là tốt! –

+0

Bạn được chào đón @Curiosity :) – Devart

+0

Chỉ cần một truy vấn Theo [link] này (dba.stackexchange.com/a/5337/27862) câu trả lời có thể có trường hợp khi cả hai điều kiện sẽ được giải quyết trong sử dụng toán tử AND vì vậy nếu đầu tiên không thành công thì nó cũng có thể áp dụng điều kiện DateAppr = 0 phải không? –

6

Để trả lời câu hỏi cơ bản về cách sử dụng biểu thức CASE trong mệnh đề WHERE:

Đầu tiên hãy nhớ rằng giá trị của biểu thức CASE phải có giá trị kiểu dữ liệu bình thường chứ không phải giá trị boolean. Nó phải là một varchar, hoặc một int, hoặc một cái gì đó. Đó là lý do tương tự bạn không thể nói SELECT Name, 76 = Age FROM [...] và mong đợi để có được 'Frank', FALSE trong tập hợp kết quả.

Ngoài ra, tất cả các biểu thức trong mệnh đề WHERE cần phải có giá trị boolean. Họ không thể có giá trị của một varchar hoặc int. Bạn không thể nói WHERE Name; hoặc WHERE 'Frank';. Bạn phải sử dụng toán tử so sánh để biến nó thành biểu thức boolean, do đó, WHERE Name = 'Frank';

Điều đó có nghĩa là biểu thức CASE phải ở một bên của biểu thức boolean. Bạn phải so sánh biểu thức CASE với một cái gì đó. Nó không thể tự đứng vững được!

đây:

WHERE 
    DateDropped = 0 
    AND CASE 
      WHEN @JobsOnHold = 1 AND DateAppr >= 0 THEN 'True' 
      WHEN DateAppr != 0 THEN 'True' 
      ELSE 'False' 
     END = 'True' 

Thông báo như thế nào cuối cùng sự biểu hiện điển hình về bên trái sẽ lần lượt biểu thức boolean vào một trong hai 'True' = 'True' hoặc 'False' = 'True'.

Lưu ý rằng không có gì đặc biệt về 'False''True'. Bạn cũng có thể sử dụng 01 nếu bạn cũng muốn.

Bạn thường có thể viết lại biểu thức CASE thành các biểu thức boolean mà chúng ta đã quen thuộc hơn và điều đó thường tốt hơn cho hiệu suất. Tuy nhiên, đôi khi dễ dàng hơn hoặc dễ bảo trì hơn khi sử dụng một biểu thức hiện có hơn là để chuyển đổi logic.

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