我有以下存储过程,该过程采用逗号分隔列表中的用户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,或以其他方式找到返回所有记录的方法,无论代码如何。
我有什么选择?
答案 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
。