6

I am trying to do the following (pseudocode since it doesn't compile):

declare showListedOrSold  int = 1 -- get value from config table

select *
from table
where CASE WHEN @showListedOrSold = 0 THEN id IN (1, 2, 5, 6, 10, 11) 
             WHEN @showListedOrSold = 1 THEN id IN (1, 5, 6, 10, 11) 
             WHEN @showListedOrSold = 2 THEN id IN (2) 
      END

Basically depending on value of showListedOrSold, it should bring back certain id values.

The statement is not liking the IN clause. What is the correct syntax for this use case?

1
  • 2
    Stay away from the CASE solutions as they're not SARGable and will create performance problems. Commented May 15, 2019 at 18:08

6 Answers 6

7

If you want an "elegant solution", you might want to consider store these values in a table that can be used in your query.

CREATE TABLE #ValidIds(
    ShowListedOrSold int,
    id int);

INSERT INTO #ValidIds
VALUES( 0, 1),
      ( 0, 2),
      ( 0, 5),
      ( 0, 6),
      ( 0, 10),
      ( 0, 11),
      ( 1, 1),
      ( 1, 5),
      ( 1, 6),
      ( 1, 10),
      ( 1, 11),
      ( 2, 2);

SELECT *
FROM table t
JOIN #ValidIds v ON t.id = v.id
AND v.ShowListedOrSold = @ShowListedOrSold;
3
  • 1
    And if you already have a config table that stores ShowListedOrSold, you could create this mapping table, and set the ShowListedOrSold value (in the config table) as a FK to the mapping table.
    – Zack
    Commented May 15, 2019 at 18:11
  • That's a bit of an overkill for my situation. This query is executed only once and this combination of numbers isn't reused anywhere. But elegant solution nonetheless. Commented May 15, 2019 at 18:53
  • The advantage is that if you have a permanent table for this, you could simply add values there instead of changing the code if more ids become available. Commented May 15, 2019 at 19:47
6

You could solve this by using OR instead of CASE:

SELECT *
FROM table
WHERE (@showListedOrSold = 0 AND id IN (1, 2, 5, 6, 10, 11))
        OR (@showListedOrSold = 1 AND id IN (1, 5, 6, 10, 11))
        OR (@showListedOrSold = 2 AND id IN (2))
4
  • I know. That's the way I have it, but it's so not elegant. Commented May 15, 2019 at 17:58
  • It would be more elegant to store the id to showlistedorsold relationship in a table, then you could just join: FROM table INNER JOIN newtable on table=id = newtable.id and @showListedOrSold = newtable.showListedOrSold
    – Greg Viers
    Commented May 15, 2019 at 18:05
  • It would, but feels like an overkill since I only need to perform this query once in my sproc. Commented May 15, 2019 at 18:07
  • Then use a table variable or temp table as Luis Cazares suggests below.
    – Greg Viers
    Commented May 15, 2019 at 18:10
5

This starts to get rather complicated. I might recommend a join approach:

select t.*
from table t join
     (values (0, 1), (0, 2), (0, 5), (0, 6), (0, 10), (0, 11),
             (1, 1), (1, 5), (1, 6), (1, 10), (1, 11),
             (2, 2)
     ) v(slos, id)
     on t.slos = @showListedOrSold and
        v.id = s.id

You can easily expand this to show all rows if the variable is null:

     on (t.slos = @showListedOrSold and
         v.id = s.id
        ) or
        @showListedOrSold is null
2

the way case works, you'd have to return a value, then check the value.

declare @showListedOrSold int = 1 -- get value from config table

select  *
from    [table]
where   (case
            when @showListedOrSold = 0 and  id in (1, 2, 5, 6, 10, 11) then 1
            when @showListedOrSold = 1 and  id in (1, 5, 6, 10, 11) then 1
            when @showListedOrSold = 2 and  id in (2) then 1
        else 0
        end) = 1
1

You could construct the SQL statement and then Execute it:

declare  @showListedOrSold Int = 1
Declare @vSQL VarChar(200)

Set @vSQL = 'select * from #tbl where id In '
Set @vSQL = @vSQL + 
                    CASE WHEN @showListedOrSold = 0 THEN '(1, 2, 5, 6, 10, 11)'
                         WHEN @showListedOrSold = 1 THEN '(1, 5, 6, 10, 11)' 
                         WHEN @showListedOrSold = 2 THEN '(2)'
                    END

Execute(@vSQL)
-1

You can give it like a sub query in WHERE clause:

select *
from table
where @showListedOrSold in (select  (CASE WHEN @showListedOrSold = 0 THEN id IN (1, 2, 5, 6, 10, 11) 
             WHEN @showListedOrSold = 1 THEN id IN (1, 5, 6, 10, 11) 
             WHEN @showListedOrSold = 2 THEN id IN (2) 
      END) as ABCD from table)
3
  • I like the slightly recursive nature of it. Commented May 15, 2019 at 18:10
  • 1
    It won't even compile Commented May 15, 2019 at 18:13
  • Case is an expression, it is used to return a scalar value. You are attempting to use to control logical flow which it cannot do.
    – Sean Lange
    Commented May 15, 2019 at 18:32

Not the answer you're looking for? Browse other questions tagged or ask your own question.