按datediff计算sql中的周天数
我正在寻找一种方法来计算两个日期之间的天数,但是在工作日。这是公式,但它计算周末按datediff计算sql中的周天数,sql,sql-server,Sql,Sql Server,我正在寻找一种方法来计算两个日期之间的天数,但是在工作日。这是公式,但它计算周末 DATEDIFF(DAY,STARTDATE,ENDDATE) SELECT DATEDIFF(DAY,'2015/06/01' , '2015/06/30') 上面查询datediff的结果是29天,这是周末。但我需要一周的天数,去掉周六和周日的8天,应该是21天。 有什么建议吗?这将返回22: 更多信息,请阅读Jeff Moden的文章 说明: 首先,DATEDIFFDAY、@StartDate、@EndD
DATEDIFF(DAY,STARTDATE,ENDDATE)
SELECT DATEDIFF(DAY,'2015/06/01' , '2015/06/30')
上面查询datediff的结果是29天,这是周末。但我需要一周的天数,去掉周六和周日的8天,应该是21天。
有什么建议吗?这将返回22:
更多信息,请阅读Jeff Moden的文章
说明:
首先,DATEDIFFDAY、@StartDate、@EndDate将返回天数的差异。在这种情况下,将是29。现在,根据您对全天的理解,您可能希望在结果中添加1天
接下来,DATEDIFFWEEK、@StartDate、@EndDate*2:
引用这篇文章:
周datepart的DATEDIFF实际上并不计算周,而是
计算日期范围包含以下日期的次数:
代表成对的周六和周日。多想想
简单来说,它只计算整个周末
因此,要排除周末,必须从第一个DATEDIFF中减去两倍的结果。现在是:29-2*4=21
最后,这是:
-(CASE WHEN DATENAME(dw, @StartDate) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, @EndDate) = 'Saturday' THEN 1 ELSE 0 END)
删除部分周,仅当@StartDate发生在星期天,@EndDate发生在星期六时才会发生。将其放入WHERE子句中
SELECT DATEDIFF(DAY,'2015/06/01' , '2015/06/30')
FROM yourtable
WHERE DATENAME(dw, StartDate) != 'Saturday'
AND DATENAME(dw, StartDate) != 'Sunday'
或全部在SELECT语句中
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)
您可以尝试递归cte:
WITH cte
AS ( SELECT CAST('2015/06/01' AS DATE) AS dt ,
DATEPART(WEEKDAY, '2015/06/01') AS wd
UNION ALL
SELECT DATEADD(d, 1, dt) AS dt ,
DATEPART(WEEKDAY, DATEADD(d, 1, dt))
FROM cte
WHERE dt < '2015/06/30'
)
SELECT COUNT(*)
FROM cte
WHERE wd NOT IN ( 7, 1 )
结果是22。
您最好添加一些每个数据库都应该具有的有用的日历表。用一些大范围填充它,然后用它来计算工作日。我编写了一个简单的存储过程-不知道SP是否是您所需要的,但我认为您可以轻松地将其转换为函数TVF,无论什么:
CREATE PROCEDURE [dbo].[BusinessdaysBetween](@DateFrom DATE, @DateTo DATE, @days INT OUTPUT)
AS
BEGIN
DECLARE @datefirst INT = @@DATEFIRST
SET DATEFIRST 1 --so week starts on monday
SET @days = 0
IF @DateFrom > @DateTo
RETURN NULL
IF @DateFrom = @DateTo
RETURN @days
WHILE @DateFrom <= @DateTo
BEGIN
IF DATEPART(WEEKDAY,@DateFrom) NOT IN (6,7) --Saturday or Sunday
BEGIN
SET @days = @days + 1
END
SET @DateFrom = DATEADD(DAY,1,@DateFrom)
END
SET DATEFIRST @datefirst --restore original setup
END
GO
SQL server的哪个版本?在复制和粘贴之前,请至少在此编辑答案it@Matt,我不是从那个答案中抄来的。请参阅我的参考文章。也许我们有相同的参考资料。请注意,我从第一个DATEDIFF中删除了+1。由于您不能使用SET命令,因此您需要在函数中检查@DATEFIRST,但我认为目前为止,在数据库和服务器上只使用了两种情况@@DATEFIRST=1周从周一开始,或@DATEFIRST=7周从周日开始。只需检查数据库中@DATEFIRST的值……您可能需要使用DATENAME,因为它不依赖@DATEFIRST。谢谢@wewesthemenance,但我认为DATENAME依赖于语言!?现在我不确定了,=显然,日期名称取决于语言。试试法语。
CREATE PROCEDURE [dbo].[BusinessdaysBetween](@DateFrom DATE, @DateTo DATE, @days INT OUTPUT)
AS
BEGIN
DECLARE @datefirst INT = @@DATEFIRST
SET DATEFIRST 1 --so week starts on monday
SET @days = 0
IF @DateFrom > @DateTo
RETURN NULL
IF @DateFrom = @DateTo
RETURN @days
WHILE @DateFrom <= @DateTo
BEGIN
IF DATEPART(WEEKDAY,@DateFrom) NOT IN (6,7) --Saturday or Sunday
BEGIN
SET @days = @days + 1
END
SET @DateFrom = DATEADD(DAY,1,@DateFrom)
END
SET DATEFIRST @datefirst --restore original setup
END
GO
DECLARE @days INT = 0
DECLARE @datefrom DATETIME = GETDATE()
DECLARE @dateto DATETIME = DATEADD(DAY,25,GETDATE())
EXEC dbo.BusinessdaysBetween @datefrom, @dateto, @days OUTPUT
SELECT @days