Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 在WHERE子句中应用条件筛选_Sql_Sql Server_Sql Server 2012 - Fatal编程技术网

Sql 在WHERE子句中应用条件筛选

Sql 在WHERE子句中应用条件筛选,sql,sql-server,sql-server-2012,Sql,Sql Server,Sql Server 2012,我在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

我在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中的任何一个大于0,那么我必须考虑WHERE子句中的筛选器;如果它等于零,我就不考虑那个特殊的条件。< /P>
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时。

首先,可以替换此J.Id=@Jobid和@Jobid>0或@Jobid=0 使用@Jobid=0或J.Id=@Jobid。 请注意,由于0显然不是职务id、员工或领导的有效值,因此and部分与此无关,因为任何记录都不会包含id 0

第二,不要使用0作为无效值,而是使用null。这不会影响性能,但这是一个更好的编程习惯,因为0在其他情况下很可能是一个有效值

第三,众所周知,catch-all查询会受到性能影响,特别是在存储过程中,因为缓存的执行计划可能不是当前执行的最佳执行计划。据我所知,处理此问题的最佳方法是向查询中添加重新编译提示,如和中所建议

因此,我建议您的查询如下所示:

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

通过对表进行正确的索引,通常可以提高select性能。然而,正确地索引需要并非所有开发人员都具备的知识。这是一个很值得一读的主题。我会的。

您可以使用这样的CASE表达式:

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
案例

当@Jiobid超过0时,它将与J.id进行比较。当不是J.id时,将其与自身进行比较,这当然会导致匹配

就我个人而言,我更喜欢@jarlh在上述评论中提出的方法。这种简单性使代码更容易理解

@jarlh示例


如果这些方法不能提高您的性能,请尝试在问题中添加您的模式和一些示例记录。你也可以考虑发布执行计划。

检查这个。简单J.ID= @ JOBID或@ JOBID=0等也会这样做。不知道会不会更快…@Mihail:我不是在找动态的SQL@jarlh:谢谢你Jarlh非常感谢你的建议。我已经选择了目标数据应答。无论如何,我会投赞成票。你也应该看看@ZoharPeled的答案。他/她在0的使用上提出了一个很好的观点。关于这个答案,有一点是——在目标列J.Id可为null的情况下,它可能会导致不正确的结果,因为null=null将计算为false。除此之外,在测试用例时,我没有看到性能的变化……当版本更新时,所以在作者看来,这是一个关于什么更具可读性的问题。
WHERE
    (J.Id = @Jobid or @Jobid=0)