2011-11-16 82 views
3

我想在SQL Server(存储过程)中执行CASE语句,我应该检查它是否应该从另一个表中获取一些结果。SQL Server:案例与声明“不在”

我只是做这件事来说明示例(不工作!)

SELECT 
    * 
FROM 
    cards 
WHERE 
    CardID = @CardID 
    AND 
    CardID = 
     CASE WHEN @AlreadyOnDeck = 1 THEN 
      IN (
        SELECT CardID FROM OnDeckTable WHERE CardID = @CardID 
      ) 
     CASE WHEN @AlreadyOnDeck = 0 THEN 
      NOT IN (
        SELECT CardID FROM OnDeckTable WHERE CardID = @CardID 
      ) 
     END 

我需要的情况下IN/NOT IN取决于@AlreadyOnDeck可变

+1

要动态生成应包含如果@AlreadyOnDeck是1而不是0,如果SQL语句的一部分吗? –

+0

IIRC您无法通过使用SELECT获取值来填充IN。 – Treborbob

回答

2

与Max的答案类似,但使用CASE语句。 (可能会产生一个稍微好一点的执行计划由于外CASE语句的短路。)

SELECT 
    * 
FROM 
    cards c 
WHERE 
    c.CardID = @CardID 
    AND 
    1 = (CASE WHEN @AlreadyOnDeck = 1 THEN 
        (CASE WHEN EXISTS(select * OnDeckTable dt where dt.CardID = c.CardID) THEN 1 END) 
       WHEN @AlreadyOnDeck = 0 THEN 
        (CASE WHEN NOT EXISTS(select * from OnDeckTable dt where dt.CardID = c.CardID) THEN 1 END)  
     END) 
2

我认为这会工作,但避风港未经测试(未提供测试数据)。

SELECT 
    * 
FROM 
    cards 
WHERE 
    CardID = @CardID 
    AND 
    (
     exists (select 1 from OnDeckTable where CardId = @CardId and @AlreadyOnDeck = 1) 
     or not exists (select 1 from OnDeckTable where CardId = @CardId and @AlreadyOnDeck = 0) 
    ) 
2
SELECT 
    * 
FROM 
    cards crd 
WHERE 
    CardID = @CardID 
    AND 
    (
    (@AlreadyOnDeck = 1 AND EXISTS(SELECT 1 FROM OnDeckTable dt WHERE dt.CardID = crd.CardID)) 
    OR 
    (@AlreadyOnDeck = 0 AND NOT EXISTS(SELECT 1 FROM OnDeckTable dt WHERE dt.CardID = crd.CardID)) 
    ) 
+0

我认为@DerekKromm的答案也有效,与此非常相似。尽管如此,句子组织在这个答案中有更多的意义和可读性。 – daniloquio

+0

是的,我同意。我已经给@ DerekKromm的答案加了+1。 – Max

1

我将与加入像这样做:

SELECT * 
FROM cards c 
LEFT JOIN OnDeckTable o ON c.CardID = o.CardID 
WHERE c.CardID = @CardID 
    AND (((@alreadyOnDeck = 0) AND (o.CardID is not null)) OR 
     ((@alreadyOnDeck = 1) AND (o.CardID is null))) 

我相信这将是比子查询更快存在的建议,但我没有测试过。

另外请注意,我没有测试上面的代码,它可能有错别字。

解决这个最快的方法是在一个以包住,如果为@alreadyOnDeck变量,类似这样的语句:

if (@alreadyOnDeck = 1) 
    -- select for this case 
else 
    -- select for this case. 

如果你的代码是在存储过程中,这将是最快的方式,输入是在查询期间不会改变。