有没有办法在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 )
我有一个存储过程,它可能会或可能不会获取 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 )