在SQL Server中获取工作日

时间:2018-02-13 10:03:08

标签: sql sql-server tsql

我之前发过这个问题,但我想我不能像我应该的那样清楚。我想计算两个日期之间的差异,我们说2018/01/012018/01/31

我有一张表Calendar,它存储的是假日和非假日。我将周日和周六标记为假期,并且想要计算剩余的工作日数,应该是23。

但实际上问题是我还可以将星期日标记为假日而不是星期六。

这也是我想要使用这张桌子的原因。我看到很多解决方案给了我23个结果,因为他们将星期日和星期六标记为假期,这也很好,但我希望它也能使用这个表。

我尝试了很多,但我确定我哪里出错了。也许现在有人可以提供帮助。

表格就像这样

CREATE TABLE Calendar
(
    Day Varchar(25), --name of the day i.e Sunday, Saturday
    IsOffDay Binary  --1 for Yes and 0 for False
)

因此,如果我将星期六和星期日标记为假日,结果应为23天,但如果我只将星期日标记为假日并使星期六无效,那么它应该是27天

一个配偶说的可能重复的建议解决方案是将星期六和星期日作为假期,但我不希望硬编码或任何你说的。

3 个答案:

答案 0 :(得分:1)

尝试使用此查询。

你的表:

 CREATE TABLE #Calendar
    ([Day] Varchar(25), --name of the day i.e Sunday, Saturday
     IsOffDay BIT  --1 for Yes and 0 for False
     )

    INSERT INTO #Calendar ([Day],IsOffDay)
    SELECT 'Sunday',1  union
    SELECT 'Saturday',0

<强>查询

DECLARE @STARTDATE  DATE='2018-01-01',@ENDDATE  DATE='2018-01-31'

;WITH CTE AS (
SELECT @STARTDATE  AS STARTDATE
UNION ALL
select DATEADD(D,1,STARTDATE) 
FROM CTE
WHERE STARTDATE <@ENDDATE
)
,WORKINGDAYS AS (
SELECT STARTDATE,DATENAME(DW,STARTDATE)WEEKDAYS,C1.Day AS isweekend
FROM CTE c
left JOIN #Calendar C1 ON DATENAME(DW,STARTDATE)=C1.Day AND C1.IsOffDay=1
)

SELECT COUNT(WEEKDAYS)as WORKINGDAYS FROM WORKINGDAYS WHERE isweekend is null

注意:以上查询为您提供Working Days =27。如果您希望星期六作为假期更新日历表IsOffDay=1 where [Day]='Saturday',那么会为您提供Working Days =23

答案 1 :(得分:0)

这有用吗??

    CREATE TABLE #Calendar
    (
        [Day] Varchar(25), --name of the day i.e Sunday, Saturday
        IsOffDay BIT  --1 for Yes and 0 for False
    )

    INSERT INTO #Calendar ([Day],IsOffDay)
    SELECT 'Sunday',1
    union
    SELECT 'Saturday',0

    --SElect * from #Calendar

    DECLARE @StartDate DATETIME='01/01/2018'
    DECLARE @EndDate DATETIME='01/31/2018'



    SELECT  TOP (DATEDIFF(DAY, @StartDate, @EndDate) + 1)
            DATENAME(dw,DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, @StartDate)) as [Day]
    INTO #tmpDays
    FROM    sys.all_objects a
            CROSS JOIN sys.all_objects b;


    --SELECT * FROM #tmpDays

    SELECT COUnt(*) as WorkingDays
    FROM #tmpDays t
    LEFT JOIN #Calendar c on t.day=c.Day
    WHERE (c.Day IS NULL)
            OR
         (c.IsOffDay =0)    


    Drop Table #Calendar
    drop table #tmpDays

答案 2 :(得分:0)

通用方法是制作一个日历表,列出几年的所有日子,并在某些法律领域将其标记为假期 - 你知道它不会是一个大表,因为10天期间它不到4000行。在这种情况下,你有一个非常灵活的解决方案,不仅可以处理周末,还可以处理假期,特殊假期,如 - 我不知道 - 哀悼日或其他什么,复活节等。

但是如果你的心脏在某些工作日被忽略了那么 -

CREATE TABLE Calendar (
  DayOfWeek tinyint, --name of the day i.e 7 for Sunday, 6 for Saturday, 1 for Monday
  IsOffDay Binary  --1 for Yes and 0 for False
)

insert into Calendar (DayOfWeek, IsOffDay) values (7,1),(6,1)

并查询:

set datefirst 1
declare @startDate date = '2018-01-01', @endDate date = '2018-01-31'
;
with numberOfDays as (
    select datediff(day, @startDate, @endDate) + 1 /*including start end end*/ as days 
),
numberOfHolidays as (
    select FLOOR(days/7) + case when DayOfWeek between datepart(dw, @startDate) and datepart(dw, @endDate) or DayOfWeek between datepart(dw, @endDate) and datepart(dw, @startDate) then 1 else 0 end as holidays
    from numberOfDays, Calendar
    where IsOffDay = 1
),
aggregatedHolidays as (
    select sum(holidays) as holidays from numberOfHolidays
)
select days - holidays
from numberOfDays, aggregatedHolidays