我正在尝试查询我的表以查找日期字段在10个工作日前与今天之间的记录。我正在努力计算10个工作日前的日期。
就我而言,假期并不重要。无论假期/工作日如何,我都只需要包括周一至周五。
我发现此SQL代码可以执行我想要的操作,但是倒退了。这将计算两个日期之间的工作日数,我需要减去一个数字并得出一个日期。
DECLARE @StartDate DATETIME
DECLARE @EndDate DATETIME
SET @StartDate = '2019-08-26'
SET @EndDate = GETDATE()
SELECT
(DATEDIFF(dd, @StartDate, @EndDate) + 1)
-(DATEDIFF(wk, @StartDate, @EndDate) * 2)
-(CASE WHEN DATENAME(dw, @StartDate) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, @EndDate) = 'Saturday' THEN 1 ELSE 0 END)
我尝试使用DATEADD
,但无法找出排除周六和周日的任何逻辑。我也不想使用某个函数,因为我绝对不需要。没有每天循环的功能,我无法在线找到有关DATEADD的任何信息。
所需功能:
START DATE: TODAY / GETDATE()
NUMBER OF BUSINESS DAYS: 10
DATEADD(DAY, -10 + CALULATE WEEKEND DAYS?, GETDATE())
答案 0 :(得分:0)
尝试如下所示的递归CTE-
DECLARE @start_date DATE= GETDATE(),
@NumberOfDays INT= 10;
WITH cte
AS
(
SELECT @start_date AS date_
UNION ALL
SELECT CAST(DATEADD(day, -1, date_) AS DATE)
FROM cte
WHERE date_ >= DATEADD(
DD,
-(@NumberOfDays + (@NumberOfDays/7+1)*3),
--Generating a approximate number consediring
--Number Of Business Day + Approximate Week Ends for that days
@start_date
)
),
CTE2 AS
(
SELECT Date_,ROW_NUMBER() OVER (ORDER BY Date_ DESC) RN
FROM cte
WHERE DATENAME(dw, Date_) NOT IN ('Saturday','Sunday')
)
SELECT Date_
FROM CTE2
WHERE RN = @NumberOfDays
OPTION(MAXRECURSION 0)
答案 1 :(得分:0)
由于您只关心周末,而不关心其他假期,因此很容易使用每个日历周(7天)中有5个工作日来计算工作日中的日历天数。如果您可以使用标量函数,则可以使用以下命令:
CREATE FUNCTION SubBusinessDays(
@days int,
@date datetime
) RETURNS int
BEGIN
SET @days = @days-1; -- number of days are inclusive of the start date
SET @date = DATEADD(DAY, -(@days / 5 * 7 + @days % 5),
DATEADD(DAY, (CASE (DATEPART(WEEKDAY, @date) + @@DATEFIRST) % 7
WHEN 0 THEN -1
WHEN 1 THEN -2
ELSE 0 END), @date));
RETURN DATEADD(DAY, (CASE WHEN (DATEPART(WEEKDAY, @date) + @@DATEFIRST) % 7 IN (0, 1)
THEN -2 ELSE 0 END), @date);
END
另一方面,如果您需要处理表,则可以使用CROSS APPLY
来执行以下示例中的步骤:
DECLARE @t TABLE(StartDate Datetime, BDays int)
INSERT INTO @t
SELECT d, ofs
FROM (VALUES ('20190906'), ('20190907'), ('20190908'), ('20190909'), ('20190910')) AS sd(d)
CROSS JOIN
(VALUES (7), (8), (9), (10), (11)) AS bd(ofs)
SELECT StartDate, BDays, EndDate
FROM @t
CROSS APPLY (SELECT BDaysMinus1 = BDays-1) x1
CROSS APPLY (SELECT EndDateTemp = DATEADD(DAY, -((BDaysMinus1 / 5) * 7 + BDaysMinus1 % 5),
DATEADD(DAY, (CASE (DATEPART(WEEKDAY, StartDate) + @@DATEFIRST) % 7
WHEN 0 THEN -1
WHEN 1 THEN -2
ELSE 0 END), StartDate))) x2
CROSS APPLY (SELECT EndDate = DATEADD(DAY, (CASE WHEN (DATEPART(WEEKDAY, EndDateTemp) + @@DATEFIRST) % 7 IN (0,1)
THEN -2 ELSE 0 END), EndDateTemp)) x3