2008-09-17 72 views

Trả lời

167

Sử dụng một tuyên bố CASE
UPDATE: Cú pháp trước đó (như chỉ ra bởi một vài người) không hoạt động. Bạn có thể sử dụng CASE như sau:

WHERE OrderNumber LIKE 
    CASE WHEN IsNumeric(@OrderNumber) = 1 THEN 
    @OrderNumber 
    ELSE 
    '%' + @OrderNumber 
    END 

Hoặc bạn có thể sử dụng câu lệnh IF như @N. J. Reed chỉ ra.

+0

[Lưu ý sau UPDATE của tác giả]: Điều đó sẽ hiệu quả, nhưng bạn nên TRIM() cả hai bên để đảm bảo tìm thấy kết quả phù hợp. Tôi có cảm giác ruột rằng có những trường hợp hiếm gặp vẫn không khớp. –

+1

Sử dụng 'CASE' là giải pháp thích hợp trong hầu hết các trường hợp. Trong trường hợp của tôi, tôi muốn thay đổi toán tử so sánh và do đó tôi đã sử dụng phương pháp tiếp theo. – Birla

6

Sử dụng một tuyên bố CASE thay vì IF.

4

Bạn muốn câu lệnh CASE

WHERE OrderNumber LIKE 
CASE WHEN IsNumeric(@OrderNumber)=1 THEN @OrderNumber ELSE '%' + @OrderNumber END 
117

Bạn sẽ có thể làm điều này mà không cần bất kỳ IF hoặc TRƯỜNG HỢP

WHERE 
    (IsNumeric(@OrderNumber) AND 
     (CAST OrderNumber AS VARCHAR) = (CAST @OrderNumber AS VARCHAR) 
OR 
    (NOT IsNumeric(@OrderNumber) AND 
     OrderNumber LIKE ('%' + @OrderNumber)) 

Tùy thuộc vào hương vị của SQL bạn có thể cần phải tinh chỉnh các diễn viên trên số thứ tự cho một INT hoặc VARCHAR tùy thuộc vào việc phôi ngầm được hỗ trợ hay không.

Đây là một kỹ thuật rất phổ biến trong mệnh đề WHERE. Nếu bạn muốn áp dụng một số logic "IF" trong mệnh đề WHERE, tất cả những gì bạn cần làm là thêm điều kiện bổ sung với một boolean AND vào phần mà nó cần được áp dụng.

+1

Tôi tưởng tượng bạn có một chút về hiệu suất đạt trên giải pháp CASE, mặc dù, vì tất cả những điều kiện đó được đánh giá, phải không? –

+0

Hoàn hảo - giải quyết được một vấn đề lâu dài đối với tôi; cảm ơn cho con trỏ! – cori

+0

Tôi luôn luôn quên rằng trong SQL có thể thay thế các câu lệnh có điều kiện bằng logic boolean như thế. Cảm ơn lời nhắc nhở, đó là một kỹ thuật rất hữu ích! – CodexArcanum

13

Không có cách nào tốt để làm điều này trong SQL. Một số phương pháp tôi đã thấy:

1) Trường hợp sử dụng kết hợp với các toán tử logic:

WHERE 
    OrderNumber = CASE 
     WHEN (IsNumeric(@OrderNumber) = 1) 
     THEN CONVERT(INT, @OrderNumber) 
     ELSE -9999 -- Some numeric value that just cannot exist in the column 
    END 
    OR 
    FirstName LIKE CASE 
     WHEN (IsNumeric(@OrderNumber) = 0) 
     THEN '%' + @OrderNumber 
     ELSE '' 
    END 

2) Sử dụng NẾU của bên ngoài SELECT

IF (IsNumeric(@OrderNumber)) = 1 
BEGIN 
    SELECT * FROM Table 
    WHERE @OrderNumber = OrderNumber 
END ELSE BEGIN 
    SELECT * FROM Table 
    WHERE OrderNumber LIKE '%' + @OrderNumber 
END 

3) Sử dụng một chuỗi dài, soạn SQL của bạn tuyên bố có điều kiện, và sau đó sử dụng EXEC

Cách tiếp cận thứ ba là ghê gớm, nhưng gần như chỉ có ý nghĩ rằng hoạt động nếu bạn có một số điều kiện biến như thế.

+0

cách tiếp cận thứ tư là chuyển đổi tất cả 'IF ... ELSE ...' điều kiện thành boolean 'AND' và' OR' như trong câu trả lời @ njr101 ở trên. Nhược điểm của^cách tiếp cận này là nó có thể gây phiền toái cho não nếu bạn có nhiều 'IF', hoặc nếu bạn có nhiều cái được lồng nhau – mmcrae

3

Tôi nghĩ rằng nơi ... như/= ... trường hợp ... sau đó ... có thể làm việc với Booleans. Tôi đang sử dụng T-SQL.

Kịch bản: Giả sử bạn muốn nhận sở thích của Person-30 nếu bool là false và sở thích của Person-42 nếu bool là true. (Theo một số, tìm kiếm sở thích bao gồm hơn 90% chu kỳ tính toán kinh doanh, do đó, hãy trả gần attn.).

CREATE PROCEDURE sp_Case 
@bool bit 
AS 
SELECT Person.Hobbies 
FROM Person 
WHERE Person.ID = 
    case @bool 
     when 0 
      then 30 
     when 1 
      then 42 
    end; 
1
 
WHERE (IsNumeric(@OrderNumber) <> 1 OR OrderNumber = @OrderNumber) 
      AND (IsNumber(@OrderNumber) = 1 OR OrderNumber LIKE '%' 
               + @OrderNumber + '%') 
+0

Quy tắc viết lại biểu mẫu bình thường chung:' NẾU P THEN Q ELSE R' '<=>' '((NOT P) HOẶC Q) VÀ (P OR R)' – onedaywhen

-6
USE AdventureWorks2012; 
GO 
IF 
(SELECT COUNT(*) FROM Production.Product WHERE Name LIKE 'Touring-3000%') > 5 
PRINT 'There are more than 5 Touring-3000 bicycles.' 
ELSE PRINT 'There are 5 or less Touring-3000 bicycles.' ; 
GO 
+0

Điều này dường như không liên quan. Nó không sử dụng một IF (hoặc bất kỳ mã điều kiện) nào trong mệnh đề WHERE. –

0

Ví dụ sau thực hiện truy vấn như một phần của biểu thức Boolean và sau đó thực hiện các khối lệnh khác nhau dựa trên kết quả của biểu thức Boolean.Mỗi khối câu lệnh bắt đầu bằng BEGIN và hoàn thành với END.

USE AdventureWorks2012; 
GO 
DECLARE @AvgWeight decimal(8,2), @BikeCount int 
IF 
(SELECT COUNT(*) FROM Production.Product WHERE Name LIKE 'Touring-3000%') > 5 
BEGIN 
    SET @BikeCount = 
     (SELECT COUNT(*) 
     FROM Production.Product 
     WHERE Name LIKE 'Touring-3000%'); 
    SET @AvgWeight = 
     (SELECT AVG(Weight) 
     FROM Production.Product 
     WHERE Name LIKE 'Touring-3000%'); 
    PRINT 'There are ' + CAST(@BikeCount AS varchar(3)) + ' Touring-3000 bikes.' 
    PRINT 'The average weight of the top 5 Touring-3000 bikes is ' + CAST(@AvgWeight AS varchar(8)) + '.'; 
END 
ELSE 
BEGIN 
SET @AvgWeight = 
     (SELECT AVG(Weight) 
     FROM Production.Product 
     WHERE Name LIKE 'Touring-3000%'); 
    PRINT 'Average weight of the Touring-3000 bikes is ' + CAST(@AvgWeight AS varchar(8)) + '.' ; 
END ; 
GO 

Sử dụng lồng nhau NẾU ... else Ví dụ sau đây cho thấy làm thế nào một if ... else statement có thể được lồng vào bên trong khác. Đặt biến @Number thành 5, 50 và 500 để kiểm tra từng câu lệnh.

DECLARE @Number int 
SET @Number = 50 
IF @Number > 100 
    PRINT 'The number is large.' 
ELSE 
    BEGIN 
     IF @Number < 10 
     PRINT 'The number is small' 
    ELSE 
     PRINT 'The number is medium' 
    END ; 
GO 
+1

Điều này có vẻ không liên quan. Nó không sử dụng một IF (hoặc bất kỳ mã điều kiện) nào trong mệnh đề WHERE. –

12

Bạn không cần tuyên bố IF chút nào.

WHERE 
    (IsNumeric(@OrderNumber) = 1 AND OrderNumber = @OrderNumber) 
OR (IsNumeric(@OrderNumber) = 0 AND OrderNumber LIKE '%' + @OrderNumber + '%') 
+1

Tôi thực sự thích cách tiếp cận này. Alternativ sử dụng: Chỉ lọc nếu AdmUseId có một giá trị: 'where (@AdmUserId là null hoặc CurrentOrder.CustomerAdmUserId = @AdmUserId)' Hoặc chỉ lọc nếu IncludeDeleted = 0: 'trong đó (@IncludeDeleted = 1 hoặc ItemObject.DeletedFlag = 0) ' –

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