Query will exclude weekends. In the query:
What is the * 2 doing in (DATEDIFF(wk, Startdate,Enddate) * 2)
Here Saturday how it will be minus (Saturday not mentioned)
(CASE WHEN DATENAME(dw, Startdate) = 'Sunday' THEN 1 ELSE 0 END)
Here how Sunday will minus (Sunday not mentioned)
(CASE WHEN DATENAME(dw, Enddate) = 'Saturday' THEN 1 ELSE 0 END)
In date diff(wk,startdate,enddate)*2) here how weekends finding and excluding exactly.
I am thinking like( 20 days-(20/7=2.6*2=5.8(Round to 6)-0-0) briefly(20-6-0-0= 14 days) is correct. but how it exactly identifying sat and sun.
I am correct or not. My question is why multiplying with 2 why can't with 3 or 4?
Query is working correctly. I am missing things in the query to understand.
Please see the query and explain clearly.
SELECT
Startdate, Enddate,
(DATEDIFF(dd, Startdate, Enddate)) -
(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 workingdays
FROM
EMP_Table;
Line by line:
First get the raw number of days between the dates:
(DATEDIFF(dd, Startdate,Enddate))
Subtract the number of weekend days, which will be the number of weeks times 2
-(DATEDIFF(wk, Startdate,Enddate )*2)
Adjust for the case where the start date is a Sunday
-(CASE WHEN DATENAME(dw, Startdate) = 'Sunday' THEN 1 ELSE 0 END)
Adjust for the case where the end date is a Saturday
-(CASE WHEN DATENAME(dw, Enddate) = 'Saturday' THEN 1 ELSE 0 END)
As pr DATEDIFF() will return the difference between two date by given interval,
and
DATENAME() will return specific part of the date which here dw will return weekday it may any day of week like Sunday, Monday etc
Now Execution of Query:
For example:
Startdate='2019/10/6' and Enddate='2019/10/12'
DATEDIFF(dd, Startdate, Enddate) will give 6
DATEDIFF(wk, Startdate, Enddate) will give 0 and there are 2 days of weekend so 0*2=0
CASE WHEN DATENAME(dw, Startdate) = 'Sunday' THEN 1 ELSE 0 END will give 1 because it's a Sunday and same as for Enddate it's a 1 due to Saturday
So final equation is workingdays=(6-0-1-1) so it give result as workingdays=4
Related
I would like to calculate a due date.
If the start date is 30/12/2020, I need to count 20 working days from start date and display the date for the 20th working date from start date.
For example if the start date is 30/12/2020 must give me 28/01/2021 (excludes saturdays and sundays and finds the 20th working day from 30/12/2020).
But I am unable to exclude the weekends.
SELECT
DATEADD(DAY,20,CAST(CAST('2020-12-30' AS DATE) AS DATETIME))
-(CASE WHEN DATENAME(dw,'2020-12-30') = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw,'2020-12-30') = 'Saturday' THEN 1 ELSE 0 END) AS DueDate
thanks
Your best pick would be to build a calendar table, with a boolean flag that indicates whether each day is a working day or not. Then you would just do something like:
select dt
from calendar
where dt >= '20201231' and is_working_day = 1
order by dt
offset 19 rows fetch next 1 row only
The way your question is asked, however, one option enumerates the days in a subquery until the count of working days is reached:
declare #dt date = '20201231';
declare #no_days int = 20;
with cte as (
select #dt as dt, #no_days as no_days
union all
select dateadd(day, 1, dt),
case when datename(weekday, dt) in ('Saturday', 'Sunday')
then no_days
else no_days - 1
end
from cte
where no_days > 1
)
select max(dt) as res from cte
If you don't care about holidays, then the 20th working day is exactly 28 days later. So you can use:
dateadd(day, 28, '2020-12-30')
Note: This assumes that the starting date is a working day.
I am trying to get the dayname from SQL, with as input only a number representing a day of the week.
When I run this code
select
datename(dw, '20210115'),
datepart(dw, '20210115')
it returns Friday, 6
So I thought that the number 6 means Friday
Then I do the following
select datename(dw, 6)
but instead of returning Friday it returns Sunday
So, what is the proper way to get the dayname from SQL Server with only a weekday number as input?
The DateName() and DatePart() rely on specific settings (e.g. SET DATEFIRST)
So whilst a value of 6 might represent "Friday" for you right now, the same code might return a different value in a different session for you or for other users.
This is why I don't use those functions, but instead create a calendar table with metadata to inform me of the week day.
The code I use looks like this:
...
, CASE WHEN DateDiff(dd, '1900-01-01', the_date) % 7 = 0 THEN 1 ELSE 0 END As is_monday
, CASE WHEN DateDiff(dd, '1900-01-01', the_date) % 7 = 1 THEN 1 ELSE 0 END As is_tuesday
, CASE WHEN DateDiff(dd, '1900-01-01', the_date) % 7 = 2 THEN 1 ELSE 0 END As is_wednesday
, CASE WHEN DateDiff(dd, '1900-01-01', the_date) % 7 = 3 THEN 1 ELSE 0 END As is_thursday
, CASE WHEN DateDiff(dd, '1900-01-01', the_date) % 7 = 4 THEN 1 ELSE 0 END As is_friday
, CASE WHEN DateDiff(dd, '1900-01-01', the_date) % 7 = 5 THEN 1 ELSE 0 END As is_saturday
, CASE WHEN DateDiff(dd, '1900-01-01', the_date) % 7 = 6 THEN 1 ELSE 0 END As is_sunday
...
This will work on all SQL Server databases, regardless of settings.
If you want this to just return the date name then it could be written as:
CASE DateDiff(dd, '1900-01-01', the_date) % 7
WHEN 0 THEN 'Monday'
WHEN 1 THEN 'Tuesday'
WHEN 2 THEN 'Wednesday'
WHEN 3 THEN 'Thursday'
WHEN 4 THEN 'Friday'
WHEN 5 THEN 'Saturday'
WHEN 6 THEN 'Sunday'
END AS day_of_week
How This Approach Works
We calculate the number of days between the input (in these examples the_date) and a known, fixed point in time.
The date 1900-01-01 is used because it is the "default" (not the right word, but I can't think of a better one right now!) i.e. what a value of 0 would be cast to.
1900-01-01 also happens to be a Monday!
Every 7th day after that is another Monday, which is what the modulus 7 (% 7) bit is responsible for working out!
This question already has answers here:
Calculating days to excluding weekends (Monday to Friday) in SQL Server
(6 answers)
Closed 4 years ago.
My simple select statement looks like this
SELECT DATEDIFF(DAY, TTHI_CREATED_ON, GETDATE()) FROM TT_TAPE_ISSUE_HD
It works perfectly. I need to exclude Thursday & Friday and display the number of days different. How can I achieve this in SQL Server?
If you wan't to avoid 2 days from a week which is Thursday & Friday you can use the below query
SELECT
(DATEDIFF(dd, TTHI_CREATED_ON, GETDATE()) + 1)
-(DATEDIFF(wk, TTHI_CREATED_ON, GETDATE()) * 2)
-(CASE WHEN DATENAME(dw, TTHI_CREATED_ON) = 'Thursday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, TTHI_CREATED_ON) = 'Friday ' THEN 1 ELSE 0 END)
Check this link it will provide you more idea,
How to calculate the number of "Tuesdays" between two dates in TSQL?
SELECT (DATEDIFF(DAY, TTHI_CREATED_ON, GETDATE())-
(datediff(day, -4, GETDATE())/7-datediff(day, -3, TTHI_CREATED_ON)/7
+ datediff(day, -4, GETDATE())/7-datediff(day, -2, TTHI_CREATED_ON)/7 )
FROM TT_TAPE_ISSUE_HD
I'm trying to figure out how to return daily results throughout the week while keeping Friday's results visible over the weekend. My current code isn't doing the trick - do I have to mess with arrays?
SELECT ROUND(COUNT(ClosedDate) / 10, 0) * 10 [Previous Day Sales]
FROM PartsSales
WHERE (MONTH(ClosedDate) = MONTH(GETDATE())) AND (YEAR(ClosedDate) = YEAR(GETDATE())) AND (DAY(ClosedDate) = **case** DAY(GETDATE())
when 1 then 1
when 2 then 2
when 3 then 3
when 4 then 4
when 5 then 5
when 6 then 5
when 7 then 5 end
You can use datepart to find the current day of the week (1 = Sunday, 2 = Monday, etc), and then you can use dateadd to go back to Friday's date. If you convert getdate() to a date, then you'll always have the "midnight" at the begining of that day.
dateadd(
day,
case datepart(dw, getdate())
when 1 then -- Sunday
-2
when 7 then -- Saturday
-1
else -- Any other day
0
end,
convert(date, getdate())
)
Is your ClosedDate a datetime datatype? You can make much better use of your indexes by checking for a date range, rather than pulling the dateparts out (using year/month/day). Below is an example with a lot of resused code in the where clause. Of course, if it is just a date datatype, you don't even need a range, since you are calculating the date.
Below is an example. It would be better if you used variables (if you're building this into a stored proc), or perhaps a derived/CTE table. I've kept things verbose for clarity.
SELECT
ROUND(COUNT(ClosedDate) / 10, 0) * 10 [Previous Day Sales]
FROM
PartsSales
WHERE
ClosedDate between
-- Today/Friday's date:
dateadd(
day,
case datepart(dw, getdate())
when 1 then -- Sunday
-2
when 7 then -- Saturday
-1
else -- Any other day
0
end,
convert(date, getdate())
)
and
-- Add 1 day to the "Today/Friday" date.
-- This is the same logic as above, except wrapped in an extra dateadd to add 1 day to it.
dateadd(
day,
1,
dateadd(
day,
case datepart(dw, getdate())
when 1 then -- Sunday
-2
when 7 then -- Saturday
-1
else -- Any other day
0
end,
convert(date, getdate())
)
)
SELECT
ScheduleDays = COUNT(DISTINCT(CAST(datediff(d, 0, a.ApptStart) AS datetime)))
FROM
Appointments a
WHERE
ApptKind = 1 AND
--filter on current month
a.ApptStart >= ISNULL(DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0),'1/1/1900') AND
a.ApptStart < ISNULL(DATEADD(month, DATEDIFF(month, 0, GETDATE())+1, 0),'1/1/3000')AND
--filter all days that aren't Friday, and then give you all Fridays that have an hour > 12.
DATENAME(weekday, a.ApptStart) <> 'Friday' and DATEPART(hour, a.ApptStart) > 12 AND
--Filter on doctor
a.ResourceID in (201)
This query will look through appointment start times and not count Fridays as our Docs only work a half day on Fridays. I was told that we do want to count them, but only as half days (first time around I was told to exclude them lol).
Could someone please help me with a Case statement that will count Fridays that do not have an appointment after 12noon, as half a day? I believe it will have to go in the ScheduleDays=COUNT(DISTINCT(CAST(datediff(d,0,a.ApptStart) as datetime))). Perhaps we can put the Friday and after 12 filters in there instead of in the where clause if we are going to use case anyways. ScheduleDays=COUNT(DISTINCT CASE WHEN etc. I really appreciate the help.
You can't really count half things using count, so that is not the way to go. But, you can do it with arithmetic. I think something like this:
select (count(distinct (case when DATENAME(weekday, a.ApptStart) <> 'Friday'
then cast(a.apptstart as date)
end)
) +
0.5 * count(distinct (case when DATENAME(weekday, a.ApptStart) = 'Friday'
then cast(a.apptstart as date)
end)
)
) as ScheduleDays
If the docs only work on Fridays for half a day, I don't think you need to check for the time of the appointment. Of course, you can if you like by adding it into the second count.
Note that to count days, I used the simpler syntax of casting the datetime to a date.
EDIT:
With the hour check:
select (count(distinct (case when DATENAME(weekday, a.ApptStart) <> 'Friday'
then cast(a.apptstart as date)
end)
) +
0.5 * count(distinct (case when DATENAME(weekday, a.ApptStart) = 'Friday' and DATEPART(hour, a.ApptStart) <= 12
then cast(a.apptstart as date)
end)
)
) as ScheduleDays