我在SELECT语句中加入了几个表,如下所示,它有三个参数。
DECLARE @Jobid INT=0,
@leadid INT=0,
@employeeid INT=0
SELECT e.id,
l.id,
j.id,
e.NAME,
l.NAME,
j.NAME
FROM employee e
INNER JOIN leads l
ON e.leadid = l.id
INNER JOIN Jobs j
ON j.id = e.Jobid
无需过滤即可正常使用。
在WHERE子句中,我必须添加如下所示的内容。如果三个ID中的任何一个大于零,那么我必须考虑WHERE子句中的过滤器;如果它等于零,我不会考虑那个特殊情况。
If @jobid> 0
then introduce this condition in where clause (j.id=@jobid)
If @leadid> 0
then introduce this condition in where clause (l.id=@leadid)
If @employeeid> 0
then introduce this condition in where clause (e.id=@employeeid)
我知道如何通过动态SQL实现这一点,但我需要一个静态SQL语句来实现这一点。
我尝试了以下内容:
where
((J.Id = @Jobid and @Jobid>0 )
or @Jobid=0)
and (
(L.Id = @leadid and @leadid>0 )
or @leadid=0
)
and (
(e.Id = @employeeid and @employeeid >0 )
or @employeeid =0
)
但是性能受到了打击。
请建议我在静态SQL中执行此操作的其他更好方法,尤其是使用Case When
。
答案 0 :(得分:4)
首先,可以替换此((J.Id = @Jobid and @Jobid>0) or @Jobid=0)
这个(@Jobid = 0 or J.Id = @Jobid)
。
请注意,由于0
显然不是作业ID(或员工或潜在客户)的有效值,因此and
部分无关紧要,因为任何记录都不会包含ID为0.
其次,请勿使用0
作为无效值,而是使用null
。它不会影响性能,但它是一种更好的编程习惯,因为0
在其他情况下很可能是一个有效的值。
第三,众所周知,catch-all查询会受到性能损失,特别是在存储过程中,因为缓存的执行计划可能不是当前执行的最佳选择。据我所知,处理此问题的最佳方法是按照this article和that article中的建议为查询添加重新编译提示。
因此,我建议您的查询如下所示:
CREATE PROCEDURE <procedure name>
(
@Jobid INT=NULL,
@leadid INT=NULL,
@employeeid INT=NULL
)
AS
SELECT e.id,
l.id,
j.id,
e.NAME,
l.NAME,
j.NAME
FROM employee e
INNER JOIN leads l
ON e.leadid = l.id
INNER JOIN Jobs j
ON j.id = e.Jobid
WHERE (@Jobid IS NULL OR J.Id = @Jobid)
AND (@leadid IS NULL OR l.Id = @leadid)
AND (@employeeid IS NULL OR e.Id = @employeeid)
OPTION(RECOMPILE)
GO
选择性能通常通过正确索引表来改进。但是,索引正确需要知识并非所有开发人员都具备。这是一个值得一读的主题。我会start here。
答案 1 :(得分:0)
您可以使用这样的CASE表达式:
CASE示例
WHERE
CASE
WHEN @Jobid > 0 THEN @Jobid -- When @Jobid supplied use it.
ELSE J.id -- When not; return current value.
END = J.id
当@Jiobid超过0时,它与J.id.如果不将J.id与自身进行比较,那当然总会导致匹配。
我个人更喜欢@jarlh在上面的评论中提出的方法。简单性使代码更容易遵循。
@jarlh示例
WHERE
(J.Id = @Jobid or @Jobid=0)
如果这些方法无法提高您的性能,请尝试在问题中添加架构和一些示例记录。您也可以考虑发布执行计划。