Reputation: 1922
This is part of a query that is calculating the total revenue for a contract based on the time-frame "This Week" along with the start and end dates of the contract (billed hourly).
SELECT (ChargeRate - PayRate) * 8 *
CASE
WHEN ContractStartDate <= DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP)
AND ContractEndDate >= CURRENT_TIMESTAMP
THEN DATEDIFF(DAY, DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP), CURRENT_TIMESTAMP)
WHEN ContractEndDate <= CURRENT_TIMESTAMP
AND ContractEndDate >= DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP)
AND ContractStartDate <= CURRENT_TIMESTAMP
THEN DATEDIFF(DAY, DATEADD(DAY, 1-DATEPART(WEEKDAY, ContractEndDate), ContractEndDate), ContractEndDate)
WHEN ContractStartDate >= DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP)
AND ContractStartDate <= CURRENT_TIMESTAMP
AND ContractStartDate >= CURRENT_TIMESTAMP
THEN DATEDIFF(DAY, ContractStartDate, CURRENT_TIMESTAMP)
WHEN ContractEndDate <= CURRENT_TIMESTAMP
AND ContractEndDate >= DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP)
AND ContractStartDate >= CURRENT_TIMESTAMP
THEN DATEDIFF(DAY, ContractStartDate, ContractEndDate)
ELSE DATEDIFF(DAY, DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP), CURRENT_TIMESTAMP)
END
What i am struggling with is how i can exclude Saturday and Sunday so the count never goes past 5 and where Sunday is not the start of the week but instead Monday. So the number of days worked would end up being [ Monday = 1, Tuesday = 2 ... Friday = 5, Saturday = 5, Sunday = 5 ]
based on what day the query is run.
What happens at the moment is that if these graphs are run on Saturday the calculation uses 6 days, if its run on Sunday the calculation uses 0 days. Every day during the week is correct, this can be seen with the following query:
DECLARE @StartDate DATETIME = '2019-12-1'
DECLARE @StartDate2 DATETIME = '2019-11-30'
SELECT DATEDIFF(DAY, DATEADD(DAY, 1-DATEPART(WEEKDAY, @StartDate), @StartDate), @StartDate)
SELECT DATEDIFF(DAY, DATEADD(DAY, 1-DATEPART(WEEKDAY, @StartDate2), @StartDate2), @StartDate2)
Results should be 0 and 6.
The only solution i can come up with is to nest the case statement and check if the value = 0 or 6 and change it to a 5, like so:
WHEN ContractStartDate <= DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP)
AND ContractEndDate >= CURRENT_TIMESTAMP
THEN
CASE
WHEN DATEDIFF(DAY, DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP), CURRENT_TIMESTAMP) IN (0,6)
THEN 5
ELSE DATEDIFF(DAY, DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP), CURRENT_TIMESTAMP)
END
which works but is a bit messy and i am interested to see if there is a better solution to this.
Upvotes: 1
Views: 87
Reputation: 5782
additional solution to already posted by @tim-monfries:
DECLARE @StartDate DATETIME = '2019-11-01';
DECLARE @EndDate DATETIME = '2019-11-30';
WITH cte AS
(
SELECT @StartDate AS SomeDate
UNION ALL
SELECT SomeDate+1 FROM cte WHERE SomeDate < @EndDate
)
SELECT COUNT(*)
FROM cte
WHERE DATENAME(dw, SomeDate) NOT IN ('Sunday', 'Saturday');
Upvotes: 1
Reputation: 71
Here's one way, borrowed from Jeff Moden via SQLServerCentral. (I'd comment this reply, but I don't have enough whacky points :( )
--count weekdays between two dates
DECLARE @StartDate DATETIME = '2019-11-01'
DECLARE @EndDate DATETIME = '2019-11-30'
SELECT (DATEDIFF(DD, @StartDate, @EndDate) + 1) --Total days in period, including weekends
-(DATEDIFF(WK, @StartDate, @EndDate) * 2) --minus number of whole weekends in the period * 2 days
-(CASE WHEN DATENAME(DW, @StartDate) = 'Sunday' THEN 1 ELSE 0 END) --minus 1 if the period starts on a Sunday
-(CASE WHEN DATENAME(DW, @EndDate) = 'Saturday' THEN 1 ELSE 0 END) --minus 1 if the period ends on a Saturday
Of course, there are issues here, such as the use of English day names that won't travel well, but those can be worked around if necessary.
I have variation of this built into a "WeekdayCount" function that comes in very handy!
Way more detail here: https://www.sqlservercentral.com/articles/calculating-work-days
Upvotes: 3