使用CASE语句在WHERE IN子句中的SQL

31

where in子句中使用case语句是否可行?像这样:

 DECLARE @Status VARCHAR(50);
 SET @Status='published';

 SELECT * FROM Product P    
 WHERE P.Status IN (CASE WHEN @Status='published' THEN (1,3)
                                   WHEN @Status='standby' THEN (2,5,9,6)
                                   WHEN @Status='deleted' THEN (4,5,8,10)
                                   ELSE (1,3)
                                   END)

这段代码出现了错误:在逗号附近语法不正确。


P.Status的类型是什么? - Maryam Arshi
你可以在 where 中使用 case,但不是这样的用法。每个语句中 case 必须返回一个值。 - Sean
@MaryamArshi:P.Status 的类型是 int。 - POIR
@SeanCoetzee。我不明白。你能给我一个例子吗? - POIR
只是问一下,THEN(2,5,9,6)有什么意义? - sathia
7个回答

43

不,你不能像这样使用casein。但是你可以这样做:

SELECT * FROM Product P    
WHERE @Status='published' and P.Status IN (1,3)
or @Status='standby' and P.Status IN  (2,5,9,6)
or @Status='deleted' and P.Status IN (4,5,8,10)
or P.Status IN (1,3)

顺便说一下,你可以把那个缩短为

SELECT * FROM Product P    
WHERE @Status='standby' and P.Status IN (2,5,9,6)
or @Status='deleted' and P.Status IN (4,5,8,10)
or P.Status IN (1,3)

or P.Status IN (1,3)的作用是获取@Status='published' and P.Status IN (1,3)以及所有符合条件的记录。


2
你不需要在每个“或”子句周围加括号吗?例如:or (@Status='standby' and P.Status IN (2,5,9,6)) - dcp
4
不要认为你需要括号,但是最后的or语句会返回错误的结果……请查看这个代码片段 - 第二条记录不应该被返回。http://sqlfiddle.com/#!3/9aef0/6 - sgeddes
AND比OR具有更强的优先级。这就是为什么在这种情况下您不需要括号的原因。 - juergen d

13

我知道这个问题已经有答案了,但是被选中的解决方案存在一个小问题。它会返回误判结果。很容易解决:

SELECT * FROM Products P    
WHERE (@Status='published' and P.Status IN (1,3))
   or (@Status='standby' and P.Status IN  (2,5,9,6))
   or (@Status='deleted' and P.Status IN (4,5,8,10))
   or (@Status not in ('published','standby','deleted') and P.Status IN (1,2))

括号不是必须的(尽管可能更容易阅读,这就是我为什么包含它们的原因)。


3
我相信你可以在where子句中使用case语句,以下是我的做法:
Select 
ProductID
OrderNo,
OrderType,
OrderLineNo
From Order_Detail
Where ProductID in (
Select Case when (@Varibale1 != '') 
then (Select ProductID from Product P Where .......)
Else (Select ProductID from Product)
End as ProductID
)

这种方法一再证明有效,请一试!


它对我起作用了,创建了一个临时表,根据参数条件插入所需的产品并与临时表连接,最后删除了临时表。 - Ramesh Venkataswamy

1
 SELECT  * FROM Tran_LibraryBooksTrans LBT  
 LEFT JOIN Tran_LibraryIssuedBooks LIB ON 
 CASE WHEN LBT.IssuedTo='SN' AND LBT.LIBRARYTRANSID=LIB.LIBRARYTRANSID THEN 1
      WHEN LBT.IssuedTo='SM' AND LBT.LIBRARYTRANSID=LIB.LIBRARYTRANSID THEN 1 
      WHEN LBT.IssuedTo='BO' AND LBT.LIBRARYTRANSID=LIB.LIBRARYTRANSID THEN 1
 ELSE 0 END

1

也许您可以尝试这种方式

SELECT * FROM Product P WHERE (CASE WHEN @Status = 'published' THEN (CASE WHEN P.Status IN (1, 3) THEN 'TRUE' ELSE FALSE END) WHEN @Status = 'standby' THEN (CASE WHEN P.Status IN (2, 5, 9, 6) THEN 'TRUE' ELSE 'FALSE' END) WHEN @Status = 'deleted' THEN (CASE WHEN P.Status IN (4, 5, 8, 10) THEN 'TRUE' ELSE 'FALSE' END) ELSE (CASE WHEN P.Status IN (1, 3) THEN 'TRUE' ELSE 'FALSE' END) END) = 'TRUE'

这样,如果@Status = 'published',则查询将检查P.Status是否在1或3中,它将返回TRUE,否则返回'FALSE'。这将与最后的TRUE匹配

希望这有所帮助。


1
根据我的场景,我使用了以下的"CASE语句在WHERE IN子句中":
@AdjType varchar(20) = 'Value', 
@Base varchar(20) = 'Common'
where 
(select CASE WHEN SA.IsPersentage = 0 THEN 'Value' 
       WHEN SA.IsPersentage = 1 THEN 'Presentage' END) Like @AdjType
and (Select CASE WHEN SA.IsDependOnBasicSalary = 0 THEN 'Common' 
        WHEN SA.IsDependOnBasicSalary = 1 THEN 'Basic Salary' END) like @Base

0
 select  * from Tran_LibraryBooksTrans LBT  left join
 Tran_LibraryIssuedBooks LIB ON   case WHEN LBT.IssuedTo='SN' AND
 LBT.LIBRARYTRANSID=LIB.LIBRARYTRANSID THEN 1 when LBT.IssuedTo='SM'
 AND LBT.LIBRARYTRANSID=LIB.LIBRARYTRANSID THEN 1 WHEN
 LBT.IssuedTo='BO' AND LBT.LIBRARYTRANSID=LIB.LIBRARYTRANSID THEN 1
 ELSE 0 END`enter code here`select  * from Tran_LibraryBooksTrans LBT 
 left join Tran_LibraryIssuedBooks LIB ON   case WHEN LBT.IssuedTo='SN'
 AND LBT.LIBRARYTRANSID=LIB.LIBRARYTRANSID THEN 1 when
 LBT.IssuedTo='SM' AND LBT.LIBRARYTRANSID=LIB.LIBRARYTRANSID THEN 1
 WHEN LBT.IssuedTo='BO' AND LBT.LIBRARYTRANSID=LIB.LIBRARYTRANSID THEN
 1 ELSE 0 END

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接