我有一个日期调用表[BadDates],它只有一列,其中每个记录都是要排除的日期。我有一个UDF如下:
CREATE FUNCTION [dbo].[udf_GetDateInBusinessDays]
(
@StartDate datetime, --Start Date
@NumberDays int --Good days ahead
)
RETURNS datetime
AS
BEGIN
-- Declare the return variable here
DECLARE @ReturnDate datetime
SET @ReturnDate = @StartDate
DECLARE @Counter int
SET @Counter = 0
WHILE @Counter < @NumberDays
BEGIN
SET @ReturnDate = DateAdd(d,1,@ReturnDate)
IF ((SELECT COUNT(ID)
FROM dbo.[BadDates]
WHERE StartDate = @ReturnDate) = 0)
BEGIN
SET @Counter = @Counter + 1
END
END
RETURN @ReturnDate
END
这个UDF效果很好,但处理速度很慢。使用它的存储过程在每个记录中运行UDF。是否有其他方法可以更快的方法提供相同的功能。
非常感谢任何帮助!
答案 0 :(得分:2)
我假设您要做的是计算在给定日期之后x个工作日的日期。什么日期是从今天起10个工作日。我还假设您的baddates表包含非工作日,例如周末和银行假期。
我在过去遇到过类似的要求,通常最后会有包含所有可能日期的天数表以及一个标志,指示某个特定日期是否为工作日。
然后我使用该表通过选择开始日期后x天的记录来计算从提供日期起x个工作日的日期。
这样的事情
CREATE TABLE all_days (
dated DATETIME,
day_state CHAR(1)
)
其中day_state是
的值
D - 工作日
W - 周末
B - 银行假期
在x个工作日后找到日期的SQL变为
SELECT MAX(dated)
FROM (
SELECT TOP(@number_days) dated
FROM all_days
WHERE day_state = 'D'
AND dated >= @start_date
ORDER by dated ASC
)
此代码未经测试但应该为您提供一般概念。您可能不希望区分周末和公共假日,在这种情况下,您可以将day_state重命名为working_day并使其成为BIT字段。
您应该在date和day_state上创建复合唯一索引。
答案 1 :(得分:2)
我没有对此进行测试,但理论上它应该可行。我把天数加起来。然后我检查该范围内是否有任何坏消息。如果有,我添加了坏天数,并检查我刚刚添加的范围内是否还有坏消息。重复,直到没有错误的日期。
CREATE FUNCTION [dbo].[udf_GetDateInBusinessDays]
(
@StartDate datetime, --Start Date
@NumberDays int --Good days ahead
)
RETURNS datetime
AS
BEGIN
-- Declare the return variable here
DECLARE @ReturnDate datetime
SET @ReturnDate = dateadd(d, @NumberDays, @StartDate);
DECLARE @d int;
SET @d = (select count(1) from baddates where startdate >= @StartDate and startdate <= @ReturnDate);
declare @t datetime;
WHILE @d > 0
BEGIN
set @t = @ReturnDate;
set @ReturnDate = dateadd(d, @d, @ReturnDate);
SET @d = (select count(1) from baddates where startdate > @t and startdate <= @ReturnDate);
END
RETURN @ReturnDate
END
答案 2 :(得分:0)
您可能希望在BadDates.StartDate上添加索引,但可能还有其他更好的解决方案。
答案 3 :(得分:0)
好的,为什么要计算何时可以使用EXISTS关键字?如果是因为你可以在Badates中有多个相同类型的日期,这似乎是错误的。 COUNT可能会查看整个表格来计算startdate的实例,只需要1即可排除。
您是否查看了查询计划以了解正在发生的事情?
答案 4 :(得分:0)
看起来您正在使用此UDF来计算两个日期之间的差异。如果我正确地解释了这个,那么我建议你使用内置的约会功能。