如何根据变量有选择地应用 WHERE IN 子句?
How to optionally apply a WHERE IN clause based on a variable?
我有一个存储过程需要按作为逗号分隔列表(即 '1,2,3'
)传递的 ID 列表进行过滤。
我想应用一个匹配这些 ID 的 WHERE IN
子句,但前提是变量包含任何内容 (IS NOT NULL AND <> ''
)。
这里是问题的简化 fiddle:http://sqlfiddle.com/#!18/5f6be/1
它目前适用于单个和多个 ID。但是当传递 ''
或 NULL
时,它应该 return 一切但它不是 returning 任何东西。
CTE 和分页的存在是有原因的,请提供不会改变它的解决方案。
使用 DelimitedSplit8k_lead
您可以通过以下方式实现:
CREATE PROC YourProc @List varchar(8000) = NULL AS
BEGIN
SELECT {YourColumns}
FROM YourTable YT
OUTER APPLY dbo.DelimitedSplit8k_Lead(@List,',') DS
WHERE DS.item = YT.YourColumn
OR NULLIF(@List,'') IS NULL
OPTION (RECOMPILE);
END
用的是OUTER APPLY
,就好像传了NULL
一样数据集不会被淘汰。 RECOMPILE
在那里,因为它变成了 "Catch-all query" 加上处理 NULL
.
老派方法:
WHERE
(@userIds IS NULL OR @userIds = '' OR U.Id IN (SELECT * FROM STRING_SPLIT(@userIds, ',')))
在末尾添加 OPTION (RECOMPILE)
以使其生效并 trim 计划。
编辑:
根据评论,此生成两个 table 扫描。它对我的 LocalDb 设置没有影响,但无论如何不要依赖它。
WHERE U.Id IN
(
SELECT * FROM STRING_SPLIT(@userIds, ',')
UNION ALL
SELECT U.Id WHERE NULLIF(@userIds, '') IS NULL
)
为什么不在 WHERE
子句中使用 JOIN
而不是子查询。
set @userIds = nullif(ltrim(@userIds),'')
select u.*
from Users u
left join string_split(@userIds,',') s on u.Id=s.value
where s.value is not null or @userIds is null
我有一个存储过程需要按作为逗号分隔列表(即 '1,2,3'
)传递的 ID 列表进行过滤。
我想应用一个匹配这些 ID 的 WHERE IN
子句,但前提是变量包含任何内容 (IS NOT NULL AND <> ''
)。
这里是问题的简化 fiddle:http://sqlfiddle.com/#!18/5f6be/1
它目前适用于单个和多个 ID。但是当传递 ''
或 NULL
时,它应该 return 一切但它不是 returning 任何东西。
CTE 和分页的存在是有原因的,请提供不会改变它的解决方案。
使用 DelimitedSplit8k_lead
您可以通过以下方式实现:
CREATE PROC YourProc @List varchar(8000) = NULL AS
BEGIN
SELECT {YourColumns}
FROM YourTable YT
OUTER APPLY dbo.DelimitedSplit8k_Lead(@List,',') DS
WHERE DS.item = YT.YourColumn
OR NULLIF(@List,'') IS NULL
OPTION (RECOMPILE);
END
用的是OUTER APPLY
,就好像传了NULL
一样数据集不会被淘汰。 RECOMPILE
在那里,因为它变成了 "Catch-all query" 加上处理 NULL
.
老派方法:
WHERE
(@userIds IS NULL OR @userIds = '' OR U.Id IN (SELECT * FROM STRING_SPLIT(@userIds, ',')))
在末尾添加 OPTION (RECOMPILE)
以使其生效并 trim 计划。
编辑: 根据评论,此生成两个 table 扫描。它对我的 LocalDb 设置没有影响,但无论如何不要依赖它。
WHERE U.Id IN
(
SELECT * FROM STRING_SPLIT(@userIds, ',')
UNION ALL
SELECT U.Id WHERE NULLIF(@userIds, '') IS NULL
)
为什么不在 WHERE
子句中使用 JOIN
而不是子查询。
set @userIds = nullif(ltrim(@userIds),'')
select u.*
from Users u
left join string_split(@userIds,',') s on u.Id=s.value
where s.value is not null or @userIds is null