有没有办法在sql的where子句中将in或=与case语句一起使用?

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

我有一个存储过程,它可能会或可能不会获取 int id 的字符串列表。当它没有得到它时,值为:' '。否则它是这样的:'500,507,908'

我正在尝试这样使用它:

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)

获取结果集,但当字符串列表为空时,此代码出错:

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.

我知道这是一个问题,id 需要 = id 而不是在 id 中。关于如何让 case 语句与 @stringList = '' then id = id else id in (SELECT * from TurnListStringIntoTable(@stringList))?

一起工作的任何想法

TurnListStringIntoTable returns 来自字符串列表的 table,在我的例子中只是项目团队 ID

我推荐布尔逻辑而不是 case 表达式:

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

不相关的旁注:如果你是 运行 SQL 服务器,正如我怀疑的那样,并且你的版本是 2016 或更高版本,你可以使用 built-in function string_split() 而不是你的客户拆分器。

当然可以!

你所要做的就是使用 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

人们可能会注意到 when 表达式不限于以任何方式查看同一变量。唯一的要求是它们必须是布尔表达式。它们按从上到下的顺序进行评估。计算结果为 true 的第一个 when 子句获胜,它的 then 值为 returned.

如果没有 else 且评估找不到匹配项,则结果值为 null

你的问题是,case 表达式

  • return 单个值,并且
  • 该值必须是同一类型。在某些情况下可以 returning 一个字符串,在另一种情况下 table 变量。

那么...您的 where 子句应如下所示:

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

您可能还会发现,在 where 子句中调用用户定义的函数将逗号分隔的字符串转换为 table 变量可能是一个坏主意™,因为对性能的影响。

您最好将 TurnListStringIntoTable 调用移到 select 语句之外,因此:

declare @list = TurnListStringIntoTable(@stringlist)

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