SQL Server: Case with the statement "NOT IN"

14,418

Solution 1

Similar to Max's answer but uses CASE statements. (May produce a slightly better execution plan due to short circuiting of the outer CASE statement.)

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)

Solution 2

I think this will work, but haven't tested (no test data provided).

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)
    )

Solution 3

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))
    )

Solution 4

I would do this with a join like so:

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)))

I believe this will be faster than the sub-query exists suggestions but I have not tested.

Also note, I did not test the code above, it may have typos.

The fastest way to solve this is to encase in one if statement for the @alreadyOnDeck variable, like this:

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

If your code is in a stored procedure this would be fastest way, the input is not going to change during the query.

Share:
14,418
janhartmann
Author by

janhartmann

Hello! I'm Jan Hartmann. With a wide set of skills, I enjoy building awesome, highly effective and performing web- and mobile and applications. http://dk.linkedin.com/in/janhartmanndk

Updated on June 08, 2022

Comments

  • janhartmann
    janhartmann about 2 years

    I am trying to do a CASE statement in SQL Server (stored procedure) where I am supposed to check if whether or not it should get some results from another table.

    I just made this up to illustrate the example (not working!)

    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
    

    I need to make the case IN / NOT IN depending on @AlreadyOnDeck variable