I'm trying to get the difference between two datetime2 fields excluding weekends.
I was able to do it only for the date but struggling to include the time:
WITH cte AS (
SELECT
start_datetime, end_datetime,
cast(datediff(dd, start_datetime, end_datetime) -
(datediff(wk, start_datetime, end_datetime) * 2) -
case when datepart(dw, start_datetime) = 1 then 1 else 0 end +
case when datepart(dw, end_datetime) = 1 then 1 else 0 end
as varchar(10)) as datediff_,
DATEDIFF(SECOND, right(start_datetime, 16), right(end_datetime, 16)) timediff_
from mytable
)
SELECT *, datediff_ + ' days, ' +
CONVERT(VARCHAR(5), timediff_/60/60)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), timediff_/60%60), 2)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), timediff_ % 60), 2) durationwoweekends
FROM cte;
This does calculate and return good when timediff_ is positive, but when negative I get a bad output:
the output format of column durationwoweekends that I'm aiming at is days, hh:mm:ss now outputting a varchar which is prob wrong and also forcing string 'days, ' but ultimately would need the field to be duration data type.
testing data:
CREATE TABLE #temptable(
start_datetime datetime2,
end_datetime datetime2
)
Insert into #temptable(start_datetime, end_datetime) values ('2022-10-31 10:30:52', '2022-11-02 23:47:55')
Insert into #temptable(start_datetime, end_datetime) values ('2022-11-01 08:30:46', '2022-11-03 02:59:27')
select * from #temptable
I'm using SQL Server 2019. Any help from any one will be greatly appreciated.

It is unusual to ignore (or adjust for) weekend dates, but not adjust for times at the same time. That might lead to strange results for cases like:
If ignoring weekend days, I believe you should ignore them in their entirety, including any time components. This can be done by mapping all datetimes from 00:00 Saturday through 24:00 Sunday as equivalent to 00:00 Monday. That would make the resulting calculations continuous and consistent. Effectively, the elapsed timer is paused from 00:00 Saturday through 24:00 Sunday (00:00 Monday).
As for calculating the date and time components for display, I would suggest:
The following will accomplish this:
CROSS APPLYs are used above to conveniently encapsulate intermediate calculations, avoid duplication of subexpressions, and to reduce clutter in the final select list.Care must be taken when working with
DATEPART(weekday, ...)values, as the values returned are dependent on theDATEFIRSTsetting, which may default to either 1 or 7 depending on the locale. The logic above handles this by first calculating comparison weekday values for known Saturday and Sunday reference dates.The
DATEDIFF(second, ...)produces an integer result good for up to about 38 years. If longer intervals are needed,DATEDIFF_BIG()may be used.Selected Results:
Set
Date/Time
Date/Time
See this db<>fiddle for a demo with a variety of test data.