我是新手,也是SQL新手。我得到了这个技巧,创建了一个标量函数,扩展了内置DateAdd
函数的功能(即排除周末和假日)。它适用于单个日期,但是当我在桌面上使用它时,它非常慢。
我已经看到一些建议使用内联表值函数。有人会如此友善地指出我的方向,我将如何将下面的内容转换为内联表值函数?我非常感激。
ALTER FUNCTION [dbo].[CalcWorkDaysAddDays]
(@StartDate AS DATETIME, @Days AS INT)
RETURNS DATE
AS
BEGIN
DECLARE @Count INT = 0
DECLARE @WorkDay INT = 0
DECLARE @Date DATE = @StartDate
WHILE @WorkDay < @Days
BEGIN
SET @Count = @Count - 1
SET @Date = DATEADD(DAY, @Count, @StartDate)
IF NOT (DATEPART(WEEKDAY, @Date) IN (1,7) OR
EXISTS (SELECT * FROM RRCP_Calendar WHERE Is_Holiday = 1 AND Calendar_Date = @Date))
BEGIN
SET @WorkDay = @WorkDay + 1
END
END
RETURN @Date
END
答案 0 :(得分:1)
这应该可以解决问题......
CREATE FUNCTION dbo.tfn_CalcWorkDaysAddDays
(
@StartDate DATETIME,
@Days INT
)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
SELECT
TheDate = MIN(x.Calendar_Date)
FROM (
SELECT TOP (@Days)
c.Calendar_Date
FROM
dbo.RRCP_Calendar c
WHERE
c.Calendar_Date < @StartDate
AND c.Is_Holiday = 0
AND c.is_Weekday = 1 -- this should be part of your calendar table. do not calculate on the fly.
ORDER BY
c.Calendar_Date DESC
) x;
GO
注意:为了获得最佳效果,您需要在日历表上添加唯一的,已过滤的非聚集索引...
CREATE UNIQUE NONCLUSTERED INDEX uix_RRCPCalendar_CalendarDate_IsHoliday_isWeekday ON dbo.RRCP_Calendar (
Calendar_Date, Is_Holiday, is_Weekday)
WHERE Is_Holiday = 0 AND is_Weekday = 1;
答案 1 :(得分:0)
说[dbo]。[CalcWorkDaysAddDays],getdate(),2将返回9月8日, 2017年,因为它增加了两天。此功能类似于DateAdd 但它不包括周末和假日
您发布的代码不会这样做。 但是如果你想要描述的结果,那么函数可以像这样:
(img)
答案 2 :(得分:0)
试试这个,看它是否返回与你的函数相同的值,只是没有循环:
SELECT WorkDays =
DATEADD(WEEKDAY, @Days, @StartDate) -
(SELECT COUNT(*)
FROM RRCP_Calendar
WHERE Is_Holiday = 1
AND Calendar_Date >= @StartDate
AND Calendar_Date <= DATEADD(DAY, @Days, @StartDate)
)
是的,使用非过程表值函数有时可以获得更好的性能,但是你必须正确设置它。查找SARGability和非过程表值函数以获取更多信息,但如果上述查询有效,则应该可以解决这个问题:
CREATE FUNCTION dbo.SelectWorkDaysAddDays(@StartDate DATE, @Days INT)
RETURNS TABLE
AS
RETURN
SELECT WorkDays =
DATEADD(WEEKDAY, @Days, @StartDate) -
(SELECT COUNT(*)
FROM RRCP_Calendar
WHERE Is_Holiday = 1
AND Calendar_Date >= @StartDate
AND Calendar_Date <= DATEADD(DAY, @Days, @StartDate)
)
GO
然后使用OUTER APPLY join:
调用该函数SELECT y.foo
, y.bar
, dt.WorkDays
FROM dbo.YourTable y
OUTER APPLY dbo.SelectWorkDaysAddDays(@StartDate, @Days) dt