Sql 计算给定日期当月的总工作日数和已用工作日数
我被SQL查询卡住了 我试图在同一个查询中计算两个不同的内容:Sql 计算给定日期当月的总工作日数和已用工作日数,sql,sql-server,sql-server-2008,datetime,Sql,Sql Server,Sql Server 2008,Datetime,我被SQL查询卡住了 我试图在同一个查询中计算两个不同的内容: 一个月内的工作日数(不包括周末) 一个月内已经过了多少个工作日 比如说11月(截至2018年11月9日) 我试着这样做: WITH cteAllDates AS ( DECLARE @StartDate DATETIME DECLARE @EndDate DATETIME SET @StartDate = '10/01/2018' SET @EndDate = '10/31/2018'
WITH cteAllDates AS
(
DECLARE @StartDate DATETIME
DECLARE @EndDate DATETIME
SET @StartDate = '10/01/2018'
SET @EndDate = '10/31/2018'
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) AS x
) AS y
SELECT x
FROM cteAllDates
我想创建一个虚拟表,以便在完整查询中使用这些字段。如果可能的话,我可以使用
GETDATE()
来实现这一点,而不是每次都声明日期。您可以尝试使用cte recursive创建日历表,然后使用条件聚合函数来获得结果
DECLARE @StartDate DATETIME
DECLARE @EndDate DATETIME
SET @StartDate = DATEADD(DAY, 1, EOMONTH(GETDATE(), -1));
SET @EndDate = DATEADD(DAY, 1, EOMONTH(GETDATE()));
;WITH CTE AS (
select @StartDate startdt,@EndDate enddt
UNION ALL
SELECT DATEADD (day ,1 , startdt) , @EndDate
FROM CTE
WHERE DATEADD (day,1,startdt) <= @EndDate
)
select SUM(CASE WHEN DATENAME(dw, startdt) NOT IN ('Sunday','Saturday') THEN 1 END) 'no.of business days',
SUM(CASE WHEN DATENAME(dw, startdt) NOT IN ('Sunday','Saturday') AND GETDATE() >= startdt THEN 1 END) 'no. of business days passed'
FROM CTE
由于您希望在CTE中执行此操作,并且基于您在SO上找到的早期答案,因此,以下是一个不需要定义开始和结束日期即可在当月执行所有操作的版本: 编辑:创建假日表的步骤 首先,创建一个假日表。不要每次都这样做,让它成为一个持久的表格,并让它充满所有你需要的假期-复活节,圣诞节等
create table holidays(holiday date)
insert holidays values ('2018-09-23'),('2018-09-24')
现在查询,包括检查日期之间的假期数
;with dates as(
select dateadd(d,-day(getdate())+1,convert(date,getdate())) as startofmonth,
dateadd(d,-1,dateadd(m,1,dateadd(d,-day(getdate())+1,convert(date,getdate())))) as endofmonth,
convert(date,getdate()) as today
)
,holidaycount as (
select count(*) as holidaysinmonth,
sum(case when holiday<=today then 1 else 0 end) as holidaystodate
from dates
join holidays on holiday between startofmonth and endofmonth
)
,daycounts as(
select dates.*,
(DATEDIFF(dd, startofmonth, endofmonth) + 1)
-(DATEDIFF(wk, startofmonth, endofmonth) * 2)
-(CASE WHEN DATENAME(dw, startofmonth) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, endofmonth) = 'Saturday' THEN 1 ELSE 0 END)
-isnull(holidaysinmonth,0) as wkdaysinmonth,
(DATEDIFF(dd, startofmonth, today) + 1)
-(DATEDIFF(wk, startofmonth, today) * 2)
-(CASE WHEN DATENAME(dw, startofmonth) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, today) = 'Saturday' THEN 1 ELSE 0 END)
-isnull(holidaystodate,0) as wkdaystodate
from dates
cross join holidaycount
)
select * from daycounts
11月的
no.of business days
是否应为22天?我建议创建一个包含大量预先计算数据的日历表,例如一个月的工作日数。在您的情况下,您可以添加一个*工作日编号“从日历的第一天开始,仅在工作日增加(也很容易排除公共假日)。现在,两个日期之间的工作日数是使用两个日历联接计算出来的差值…@D-Shih..此查询没有返回任何结果。@jsingh sqlfiddle很好…也许您可以检查@StartDate
和@EndDate
var@TomC..Thanku谢谢你回答我这真的很好但是我想知道,在11月,我是否愿意将11月23日和24日排除在外(我的意思是这些是假期)。我将如何将其添加到此查询中?一旦您开始添加假日,那么您将转到评论和其他答案中的其他建议-您将创建一个单独的日历表,其中包括每个日期,以及工作日、假日等的标志。然后,这就成了计算相关天数的简单示例。@TomC..您能告诉我怎么做吗w是否要执行此操作?。在11月,我想排除11月22日。我将如何创建日历表?我已更新为使用仅包含假日日期的简单假日表。请确保只输入周假日。@TomC..您好,我收到一个错误,数据库中已经有一个名为“假日”的对象。
create table holidays(holiday date)
insert holidays values ('2018-09-23'),('2018-09-24')
;with dates as(
select dateadd(d,-day(getdate())+1,convert(date,getdate())) as startofmonth,
dateadd(d,-1,dateadd(m,1,dateadd(d,-day(getdate())+1,convert(date,getdate())))) as endofmonth,
convert(date,getdate()) as today
)
,holidaycount as (
select count(*) as holidaysinmonth,
sum(case when holiday<=today then 1 else 0 end) as holidaystodate
from dates
join holidays on holiday between startofmonth and endofmonth
)
,daycounts as(
select dates.*,
(DATEDIFF(dd, startofmonth, endofmonth) + 1)
-(DATEDIFF(wk, startofmonth, endofmonth) * 2)
-(CASE WHEN DATENAME(dw, startofmonth) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, endofmonth) = 'Saturday' THEN 1 ELSE 0 END)
-isnull(holidaysinmonth,0) as wkdaysinmonth,
(DATEDIFF(dd, startofmonth, today) + 1)
-(DATEDIFF(wk, startofmonth, today) * 2)
-(CASE WHEN DATENAME(dw, startofmonth) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, today) = 'Saturday' THEN 1 ELSE 0 END)
-isnull(holidaystodate,0) as wkdaystodate
from dates
cross join holidaycount
)
select * from daycounts
,holidays as (
select holiday from (values ('2018-11-23'),('2018-11-24')) t(holiday)
)
,holidaycount as (