【问题标题】:Using the COALESCE and IN keywords in the same sql statement在同一个 sql 语句中使用 COALESCE 和 IN 关键字
【发布时间】:2013-07-12 10:43:51
【问题描述】:
我想从使用IN关键字的参数中选择记录的数据库中选择结果:
SELECT * FROM report_view
WHERE project_id = 1
AND versionName IN (SELECT LTRIM(string) COLLATE DATABASE_DEFAULT FROM [dbo].[func_ParseString](@milestoneInput))
这很好,但如果 IN 语句中没有返回任何内容,我想使用 COALESCE 关键字来恢复所有内容。
有没有办法做到这一点?
【问题讨论】:
标签:
sql
sql-server
coalesce
【解决方案1】:
使用COALESCE 将单列 中的NULL 替换为给定值。使用NOT EXISTS 在结果表中指定无无行条件。看起来你想要的是:
SELECT * FROM report_view
WHERE project_id = 1
AND (
versionName IN (
SELECT LTRIM(string) COLLATE DATABASE_DEFAULT
FROM [dbo].[func_ParseString](@milestoneInput)
)
OR NOT EXISTS (
SELECT 1
FROM report_view
WHERE project_id = 1
AND versionName IN (
SELECT LTRIM(string) COLLATE DATABASE_DEFAULT
FROM [dbo].[func_ParseString](@milestoneInput)
)
)
)
我不确定这会调用你的函数多少次。使用UNION ALL 而不是OR,你可能会更好:
;WITH VersionNames AS (
SELECT LTRIM(string) COLLATE DATABASE_DEFAULT AS versionName
FROM [dbo].[func_ParseString](@milestoneInput)
)
SELECT *
FROM report_view
WHERE project_id = 1
AND versionName IN (SELECT versionName from VersionNames)
UNION ALL
SELECT *
FROM report_view
WHERE project_id = 1
AND NOT EXISTS
(
SELECT 1
FROM report_view
WHERE project_id = 1
AND versionName IN (SELECT versionName from VersionNames)
)
我不确定使用 CTE 是仅仅相当于语法糖,还是实际上强制函数只评估一次;其他人可以对此进行调查并提供正确的答案:)
【解决方案2】:
这是一个将所有逻辑放在exists 子句中的替代方法。
这个想法是使用窗口函数来查看是否有任何匹配以及确定特定字符串是否匹配。
SELECT *
FROM report_view
WHERE project_id = 1 and
exists (select 1
from (SELECT sum(case when ltrim(ps.string) = rv.VersionName then 1 else 0
end) over () as NumMatches,
(case when ltrim(ps.string) = rv.VersionName then 1 else 0
end) as IsMatch
FROM [dbo].[func_ParseString](@milestoneInput) ps
) t
where IsMatch = 1 or NumMatchs = 0
)
关键是where 子句,它表示当值匹配或列表中没有匹配时返回true。