Sql server 使用Case或Join的TSQL Select语句

Sql server 使用Case或Join的TSQL Select语句,sql-server,tsql,stored-procedures,sql-server-2012,Sql Server,Tsql,Stored Procedures,Sql Server 2012,我有点陷入了一个我一直在努力克服的局面。我有一个页面,允许用户选择他们想要搜索的所有过滤器选项,然后对该数据运行查询 每个领域都需要挑选一些东西,但在我介绍的一个新领域,它将是可选的 它允许您提供一份主管列表,然后它将提供代理主管在所提供列表中的所有记录;非常直截了当。但是,我尝试将此设置为可选设置,因为我不希望总是按用户搜索。如果我没有在UI中提供要传递给存储过程的名称,那么我希望忽略语句的这一部分,并获取所有内容,而不考虑管理器 以下是我正在处理的查询: SELECT a.[escID],

我有点陷入了一个我一直在努力克服的局面。我有一个页面,允许用户选择他们想要搜索的所有过滤器选项,然后对该数据运行查询

每个领域都需要挑选一些东西,但在我介绍的一个新领域,它将是可选的

它允许您提供一份主管列表,然后它将提供代理主管在所提供列表中的所有记录;非常直截了当。但是,我尝试将此设置为可选设置,因为我不希望总是按用户搜索。如果我没有在UI中提供要传递给存储过程的名称,那么我希望忽略语句的这一部分,并获取所有内容,而不考虑管理器

以下是我正在处理的查询:

SELECT a.[escID],
           a.[escReasonID],
           b.[ArchibusLocationName],
           c.[ArchibusLocationName],
           b.[DepartmentDesc],
           c.[DepartmentDesc],
           a.[escCreatedBy],
           a.[escWorkedBy],
           a.[escNotes],
           a.[preventable],
           a.[escalationCreated],
           a.[escalationTracked],
           a.[feedbackID],
           typ.[EscalationType],
           typ.[EscalationTypeText] AS escalationType,
           d.reasonText AS reasonText
    FROM   [red].[dbo].[TFS_Escalations] AS a
           LEFT OUTER JOIN
           red.dbo.EmployeeTable AS b
           ON a.escCreatedBy = b.QID
           LEFT OUTER JOIN
           red.dbo.EmployeeTable AS c
           ON a.escWorkedBy = c.QID
           LEFT OUTER JOIN
           red.dbo.TFS_Escalation_Reasons AS d
           ON a.escReasonID = d.ReasonID
           INNER JOIN
           dbo.TFS_EscalationTypes AS typ
           ON d.escType = typ.EscalationType
    WHERE  B.[ArchibusLocationName] IN (SELECT location
                                        FROM   @tmLocations)
           AND C.[ArchibusLocationName] IN (SELECT location
                                            FROM   @subLocations)
           AND B.[DepartmentDesc] IN (SELECT department
                                      FROM   @tmDepartments)
           AND C.[DepartmentDesc] IN (SELECT department
                                      FROM   @subDepartments)
           AND DATEDIFF(second, '19700101', CAST (CONVERT (DATETIME, A.[escalationCreated], 121) AS INT)) >= @startDate
           AND DATEDIFF(second, '19700101', CAST (CONVERT (DATETIME, A.[escalationCreated], 121) AS INT)) <= @endDate
           AND a.[PREVENTABLE] IN (SELECT PREVENTABLE FROM @preventable)
           AND b.MgrQID IN (SELECT leaderQID FROM @sourceLeaders)
基本上,如果临时表
@sourceLeaders
中没有数据,那么它应该忽略该查询部分


WHERE
子句的所有其他实例中,这些字段总是需要一些东西,这就是为什么所有字段都可以正常工作的原因。根据临时表中是否包含数据(临时表由用户可以搜索的用户界面中输入的名称填充),我无法找出使这一部分可选的最佳方法。

因此,如果与表变量中的数据匹配或表变量中没有任何内容,则这一行应该为真

AND 
(
   b.MgrQID IN (SELECT leaderQID FROM @sourceLeaders)
   OR
   NOT EXISTS (SELECT 1 FROM @sourceLeaders)
)

与Nick.McDermaid的类似,但使用案例陈述:

AND 
(
   1 = CASE WHEN NOT EXISTS(SELECT 1 FROM @sourceLeaders) THEN  1
            WHEN b.MgrQID IN (SELECT leaderQID FROM @sourceLeaders) THEN 1
            ELSE 0 
       END 
)   

也许在最上面,所以你只有一张支票

DECLARE @EmptySourceLeaders CHAR(1)
IF EXISTS (SELECT 1 FROM @sourceLeaders)
   SET @EmptySourceLeaders = 'N'
ELSE 
   SET @EmptySourceLeaders = 'Y'
然后在连接中

LEFT OUTER JOIN @SourceLeaders SL
ON b.MgrQID = SL.leaderQID
那么在哪里呢

AND  (@EmptySourceLeaders = 'Y' OR SL.leaderQID IS NOT NULL)

有很多方法可以做到这一点。

这是不是缺少了一些括号?它的意思是语法错误虽然这确实允许我执行查询,但它最终超时了。它不是在某个地方卡住了,就是对性能产生了实质性的影响。是的,我确信它会影响性能。您可以通过使用联接而不是在。。。但不管怎样,请看这个,它有一个很好的讨论,一个关于这个设计模式的好链接:。这个可选参数的性能问题是众所周知的,也得到了很好的讨论。别忘了关注到Erlands博客的链接,它有很多信息:可选参数-甚至还有一个比较长的讨论,比较了3种最常用的技术(局部变量、重新编译和优化未知):我认为Nick的答案是有意义的,但如果您希望选择所有项目,则最好完全填充@sourceLeaders表参数。这是我在其他项目中所做的,但这是从拥有65000多条记录的员工表中挑选主管。。。我不知道更好的解决办法是什么。是的,尼克的答案更简单。我唯一想到的另一种方法是应用其他参数(地点、部门等)并减少employee表中的结果。我尝试过这种方法,当
@sourceLeaders
表中有一个名称时效果很好,但当我没有按特定的人搜索时,我的任何条件都没有结果。这很奇怪。作为测试,我建议将CASE语句从WHERE部分移动到查询的SELECT部分。然后您可以看到CASE函数返回了什么。e、 g.选择a、b、案例。。。结束作为案例结果,d来自。。。
AND  (@EmptySourceLeaders = 'Y' OR SL.leaderQID IS NOT NULL)