简体   繁体   中英

Is there a way to use in or = with a case statement in the where clause in sql?

I have a stored procedure that may or may not get a string list of int ids. When it doesn't get it the value is: ' '. Other wise its something like this: '500,507,908'

I'm trying to use it like this:

select ID as projectTeamId, Employee_ID, Supervisor_ID 
from ProjectTeam 
where Project_ID = @projectId and IsDeleted = 0 and 
        ID in (CASE @stringList WHEN '' THEN ID ELSE (SELECT * from TurnListStringIntoTable(@stringList)) END)

to get a result set but it errors out with this code when the string list comes in blank:

An error has occurred while processing Report 'MassReleaseHoursReport': Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

I know its an issue where id needs to = id instead of being in id. Any ideas on how I can have the case statement work with @stringList = '' then id = id else id in (SELECT * from TurnListStringIntoTable(@stringList))?

TurnListStringIntoTable returns a table from a string list which in my case is just the project Team ID

I would recommend boolean logic rather than a case expression:

where 
    Project_ID = @projectId 
    and IsDeleted = 0 
    and (
        @stringList = ''
        or id in (select * from TurnListStringIntoTable(@stringList))
    )

Unrelated side note: if you are running SQL Server, as I suspect, and your version is 2016 or higher, you can use built-in function string_split() instead of your customer splitter.

Sure!

All you have to do is use the parameterless flavor of case :

select *
from my_table t
where t.col_1 = case
         when @var in (1,2,3) then "foo"
         when @var =   4      then "bar"
         when @var in (5,6,7) then "baz"
         else                      "bat"
       end

One might note that the when expressions are not limited to looking at the same variable in any way. The only requirement is that they have to be a boolean expression. They're evaluated in order top to bottom. The first when clause that evaluates to true wins and it's then value is returned.

If there's no else and evaluation fails to find a match, the result value is null .

Your problem though, is that case expressions

  • return a single value, and
  • that value must be of the same type. Can have it returning a string in some cases and a table variable in another.

So... your where clause should look something like this:

where ...
  and 'true' = case
                 when @stringList = '' then 'true'
                 when ID in ( select *
                              from TurnListStringIntoTable(@stringList)
                            ) then 'true'
                 else 'false'
               end

You'll probably find, too, that invoking a user-defined function to convert a comma-delimited string into a table variable within the where clause is probably a Bad Idea™ due to the performance impact that that will have.

You'd be better off to move your TurnListStringIntoTable call outside of the select statement, thus:

declare @list = TurnListStringIntoTable(@stringlist)

select ...
from ProjectTeam pt
where . . .
  and @stringlist = ''
   OR exists ( select * from @list x where x.ID = pt.ID )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM