I have posted this problem ago but I guess I wasn't able to be as clear as I should have. I want to calculate difference between 2 dates let's say 2018/01/01
and 2018/01/31
.
I have a table Calendar
which is storing what day is a holiday and what is not. I am marking Sunday and Saturday as holidays, and want to calculate the working days remaining which should be 23.
But what actually the problem is that I can also mark Sunday as holiday and not Saturday.
That's why I want to use this table as well. I see so many solutions that are giving me 23 result because they are marking Sunday and Saturday as holiday which is fine too but I want it to be using this table as well.
I tried much but I'm sure where I am going wrong. Maybe somebody can help now.
Table is like this
CREATE TABLE Calendar
(
Day Varchar(25), --name of the day i.e Sunday, Saturday
IsOffDay Binary --1 for Yes and 0 for False
)
So if I mark Saturday and Sunday as holiday the result should be 23 days but if I only mark Sunday as holiday and make Saturday inactive then it should be 27 days
The proposed solution that one mate says is possible duplicate is getting Saturday and Sunday as holiday but I don't want that to be hard coded or whatever you say.
Try with this query .
Your Table :
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
Query
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
Note: The above query gives you Working Days =27
.If you want saturday as holiday Update Calendar table IsOffDay=1 where [Day]='Saturday'
then gives you Working Days =23
Is this helpfull.?
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
GEneral approach would be to make a calendar table that lists all the days for few years and marks them as holidays under certain law areas - you know it won't be big table as for a 10y period it's under 4000 rows. In this case you have very flexible solution that will handle not only weekends but also holidays, ad-hoc holidays like - I don't know - day of mourning or whatever, Easter etc.
But if your heart is set on omitting certain weekdays then -
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)
And query:
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