绕过查询中的最后一个INNER JOIN

时间:2010-09-30 12:52:22

标签: sql sql-server-2005 stored-procedures

我有以下存储过程,该过程采用逗号分隔列表中的用户ID,开始日期,结束日期和代码列表,并返回与这两个日期之一匹配的所有活动记录。列表中的代码。

ALTER PROCEDURE [dbo].[ActivitiesSummary] 

@UserID varchar(30),
@StartDate datetime,
@EndDate datetime,
@Codes varchar(100)

AS

BEGIN

 SET NOCOUNT ON;

 SELECT act.SectionID, act.UnitID, act.ActivityCode
 FROM dbo.Activities act INNER JOIN ConvertCodeListToTbl(@Codes) i ON act.ActivityCode = i.code
 WHERE act.ActivityDate>=@Startdate AND act.ActivityDate<@EndDate
 GROUP BY act.SectionID, act.UnitID, act.ActivityCode
 ORDER BY act.SectionID, act.UnitID, act.ActivityCode
END

ConvertCodeListToTbl(@Codes)是一个以逗号分隔的代码列表(例如,'A0001,B0001,C0001')并返回一个每行一个代码的表的函数:

A0001
B0001
C0001

除非没有选择代码,否则此方法非常有效。发生这种情况时,我没有收到任何记录,因为@ Codes =''而最后一个INNER JOIN没有返回任何记录。

我想要发生的事情:如果@ Codes ='',忽略最后的INNER JOIN,或以其他方式找到返回所有记录的方法,无论代码如何。

我有什么选择?

5 个答案:

答案 0 :(得分:1)

听起来你需要将INNER JOIN行更改为:

FROM dbo.Activities act INNER JOIN ConvertCodeListToTbl(@Codes) i 
ON (act.ActivityCode = i.code OR @Codes = '')

答案 1 :(得分:0)

我不确定如何在SQL中执行此操作而不会搞砸查询计划(例如,您可以使用动态sql执行此操作,但之后您将生成两个非常不同的查询)。 / p>

您的调用应用程序必须知道@codes在调用存储过程之前是空的,那么为什么不让它调用不执行连接的其他存储过程呢?

答案 2 :(得分:0)

您可以在join语句中添加另一个条件。这可能不是有效的sql server语法,而是执行类似

的操作
... i ON (act.ActivityCode = i.code) OR IF(@codes = '', 1, 0)
如果@codes为空,

基本上会在任何地方加入。

答案 3 :(得分:0)

在SQL Server中,您可以为存储过程中的参数设置默认值。

将您的行顶部更改为:

@Codes varchar(100) = '*'

然后你的另一个proc ConvertCodeListToTbl如果传递'*'作为参数,则返回所有值。

答案 4 :(得分:0)

我不知道性能会如何比较,但这应该是一个完全符合你想要的查询:

SELECT act.SectionID, act.UnitID, act.ActivityCode 
FROM dbo.Activities act
WHERE act.ActivityDate>=@Startdate AND act.ActivityDate<@EndDate
    AND (@Codes = '' OR
         EXISTS
           (SELECT *
            FROM ConvertCodeListToTbl(@Codes)
            WHERE act.ActivityCode = code))
GROUP BY act.SectionID, act.UnitID, act.ActivityCode 
ORDER BY act.SectionID, act.UnitID, act.ActivityCode

另一个选择是在输入为空时让ConvertCodeListToTbl返回SELECT ActivityCode FROM dbo.Activities