Split time records across midnight - sql

I'm trying to run some reports and having to deal with the whole issue of employee labor hours crossing midnight. It occurs to me though that I could split the records that cross midnight into two records as if the employee clocked out at midnight and simultaneously clocked back in at midnight thus avoiding the midnight problem altogether.
So if I have:
EmployeeId InTime OutTime
--- ----------------------- -----------------------
1 2012-01-18 19:50:04.437 2012-01-19 03:30:02.433
What do you suppose would be the most elegant way to split this record like so:
EmployeeId InTime OutTime
--- ----------------------- -----------------------
1 2012-01-18 19:50:04.437 2012-01-19 00:00:00.000
1 2012-01-19 00:00:00.000 2012-01-19 03:30:02.433
And yes, I have thoroughly thought through what effects this might have on existing functionality... which is why I'm opting to do this in a temporary table that will not affect existing functionality.

This might help:
DECLARE #tbl TABLE
(
EmployeeId INT,
InTime DATETIME,
OutTime DATETIME
)
INSERT INTO #tbl(EmployeeId,InTime,OutTime) VALUES (1,'2012-01-18 19:50:04.437','2012-01-19 03:30:02.433')
INSERT INTO #tbl(EmployeeId,InTime,OutTime) VALUES (2,'2012-01-18 19:50:04.437','2012-01-18 20:30:02.433')
INSERT INTO #tbl(EmployeeID,InTime,OutTime) VALUES (3,'2012-01-18 16:15:00.000','2012-01-19 00:00:00.000')
INSERT INTO #tbl(EmployeeID,InTime,OutTime) VALUES (4,'2012-01-18 00:00:00.000','2012-01-18 08:15:00.000')
SELECT
tbl.EmployeeId,
tbl.InTime,
DATEADD(dd, DATEDIFF(dd, 0, tbl.OutTime), 0) AS OutTime
FROM
#tbl AS tbl
WHERE
DATEDIFF(dd,tbl.InTime,tbl.OutTime)=1
UNION ALL
SELECT
tbl.EmployeeId,
CASE WHEN DATEDIFF(dd,tbl.InTime,tbl.OutTime)=1
THEN DATEADD(dd, DATEDIFF(dd, 0, tbl.OutTime), 0)
ELSE tbl.InTime
END AS InTime,
tbl.OutTime
FROM #tbl AS tbl
ORDER BY EmployeeId

The following solution uses a numbers table (in the form of a subset of the master..spt_values system table) to split the time ranges. It can split ranges spanning an arbitrary number of days (up to 2048 with spt_values, but with your own numbers table you can set a different maximum). The specific cases of 1- and 2-day spanning ranges are not addressed here, but I believe the method is lightweight enough for you to try:
;
WITH LaborHours (EmployeeId, InTime, OutTime) AS (
SELECT
1,
CAST('2012-01-18 19:50:04.437' AS datetime),
CAST('2012-01-18 03:30:02.433' AS datetime)
),
HoursSplit AS (
SELECT
h.*,
SubInTime = DATEADD(DAY, DATEDIFF(DAY, 0, h.InTime) + v.number + 0, 0),
SubOutTime = DATEADD(DAY, DATEDIFF(DAY, 0, h.InTime) + v.number + 1, 0)
FROM LaborHours h
INNER JOIN master..spt_values v
ON number BETWEEN 0 AND DATEDIFF(DAY, h.InTime, h.OutTime)
WHERE v.type = 'P'
),
HoursSubstituted AS (
SELECT
EmployeeId,
InTime = CASE WHEN InTime > SubInTime THEN InTime ELSE SubInTime END,
OutTime = CASE WHEN OutTime < SubOutTime THEN OutTime ELSE SubOutTime END
FROM HoursSplit
)
SELECT *
FROM HoursSubstituted
Basically, it's a two-step method.
First we use the numbers table to duplicate every row so many times as the number of days the range spans and to prepare ‘standard’ sub-ranges starting at midnight and ending at the next midnight.
Next, we compare the beginning of a sub-range with the beginning of the range to see whether it is the first sub-range, in which case we use InTime as its beginning. Similarly, we compare the endings to see whether we should use OutTime or just the midnight as the end of that subrange.

If for the report, then you should just be able to do a query / union that give two records during those conditions from the original one starting... Without having SQL-Server 2008, I can only offer a pseudo-code query for you.
The first part of the gets all records based on whatever your range condition to show. The value of the "OutTime" is conditional... if its on the same day, then no cross over, just use the out time. If it IS on the next day, use casting to dynamically build out a 'YYYY-MM-DD' date (which will default to 00:00:00 time) as you want as the OUT time.
The UNION will ONLY grab those same records qualified in the FIRST where the in/out dates are DIFFERENT. As such, we KNOW we want whatever the OutTime was to act as the InTime, but based on the "00:00:00" time, so the exact same casting of a date/time field is performed, and for these records, just use the final "OutTime" value as-is.
The extra column for "TimeSplit" of '1' or '2' is to make sure that we can still group by employee ID, but from that, ensure that the '1' entries (starting shift) are first, followed by any for the respective same person have a '2' entry for the day overlap in their shift.
select
tc.EmployeeID,
'1' as TimeSplit,
tc.InTime,
case when datepart( dd, tc.InTime ) = datepart( dd, tc.OutTime )
then tc.OutTime
else CAST( CAST( datepart(yyyy, tc.OutTime ) AS varchar)
+'-'+ CAST( datepart( mm, tc.OutTime ) AS varchar)
+'-'+ CAST( datepart( dd, tc.OutTime ) AS varchar) AS DATETIME)
end as OutTime
from
TimeCard tc
where
YourDateRangeConditions...
ORDER BY
tc.EmployeeID,
TimeSplit
UNION ALL
select
tc.EmployeeID,
'2' as TimeSplit,
CAST( CAST( datepart(yyyy, tc.OutTime ) AS varchar)
+'-'+ CAST( datepart( mm, tc.OutTime ) AS varchar)
+'-'+ CAST( datepart( dd, tc.OutTime ) AS varchar) AS DATETIME)
end as InTime
tc.OutTime
from
TimeCard tc
where
YourDateRangeConditions...
AND NOT datepart( dd, tc.InTime ) = datepart( dd, tc.OutTime )

Building on accepted answer, as a newbie on mysql I expanded the code to better understand each scenario
SELECT
tbl.EmployeeId,
Datediff(tbl.OutTime, tbl.InTime) as DD,
-- Change outTime to end of the day if shift is overnight
DATE_FORMAT(tbl.InTime, "%Y-%m-%d %H:%i:%s") as InTime,
CASE WHEN Datediff(tbl.OutTime, tbl.InTime) = 1
THEN DATE_FORMAT(tbl.OutTime, "%Y-%m-%d 00:00:00")
ELSE DATE_FORMAT(tbl.OutTime, "%Y-%m-%d %H:%i:%s")
END AS OutTime
FROM tbl
UNION DISTINCT
SELECT
tbl.EmployeeId,
Datediff(tbl.OutTime,tbl.InTime) as DD,
-- Change inTime to beginning of the next day if shift is overnight
CASE WHEN Datediff(tbl.OutTime,tbl.InTime) = 1
THEN DATE_FORMAT(tbl.OutTime, "%Y-%m-%d 00:00:00")
ELSE DATE_FORMAT(tbl.InTime, "%Y-%m-%d %H:%i:%s")
END AS InTime,
DATE_FORMAT(tbl.OutTime, "%Y-%m-%d %H:%i:%s") as OutTime
FROM tbl
order by EmployeeId

Try this, because you can do an insert off of a select and inside your select you can set the values to use to be different days.
For Adding the new row:
insert into table ("EMPLOYEE_ID","INTIME","OUTTIME") values
SELECT EMPLOYEE_ID,date(INTIME),OUTTIME
FROM table
where date(intime) < date(outtime)
Updating the original row:
update table
set outtime =date(outtime)
where date(intime)= date(outtime)

Related

SQL Query needed for desired Output

Below is the sample data which gets filled into sql server database from different PLC machine. datetime,machineID, cycletime(TIME TAKEN TO PRODUCE THAT MATERIAL) AND shift
There are 3 shifts in company A(6:30Am to 2:30PM), B(2:30 to 10:30), C(10:30 to 6:30AM).
when i take C Shift count, my query should take next day data also till 6:30AM time. Where as A shift should take current day data starting from 6:30Am to 2:30Pm.Where as B shift should take current day data starting from 2:31pm to 10:30PM.
Desired Output::
I need to find the quantity for each hour...6:30 to 7:30 what is the quantity... 7:30 to 8:30 what is the quantity and so on for each individual hour. Quantity should not get added with previous hour quantity.. individual hour quantity
You can start with this, and then wrap it with
"SELECT ... just the columns you want
FROM this example
GROUP BY ...."
SELECT
-- isolate Date from Time from HourMinutes only for testing
CONVERT(VARCHAR(10), [MDate], 111) as RealDate
,CONVERT(VARCHAR, [MTime], 108) as RealTime
,SUBSTRING(CONVERT(VARCHAR, [MTime], 108),4,5) as HrMn
-- from midnight to 6:30 adjust to prior day
, Case When (CONVERT(VARCHAR, [MTime], 108) < '06:30:00')
Then CONVERT(VARCHAR(10), DATEADD(day,-1,[MDate]), 111)
Else CONVERT(VARCHAR(10), [MDate], 111)
End as RptDate
-- from after the half hour, report it with the next hour
,Case When (SUBSTRING(CONVERT(VARCHAR, [MTime], 108),1,5)) > '23:30:00'
Then ' 0:30'
When (SUBSTRING(CONVERT(VARCHAR, [MTime], 108),4,5)) > '30:00'
Then STR(DATEPART ( hour , [MTime] ) + 1, 2) + ':30'
Else STR(DATEPART ( hour , [MTime] ), 2) + ':30'
End as RptHour
,[MachinelD]
,[CYCLETIM]
,[Shift]
FROM [StackOver].[dbo].[CShift]
For your add-on question of getting only Previous or Current shift,
we need to think ahead to what the Where clause might look like--
Where (MDate = #fromDate and MTime >= #fromTime)
Or (MDate > #fromDate)
And then, before the main SELECT/FROM, create appropriate local vars --
Declare #fromDate as datetime, #fromTime as datetime
If CONVERT (time, GETDATE()) <= '06:30:00' Begin
Set #fromDate=DATEADD(day,-1,CONVERT (date, GETDATE())) --yesterday
Set #fromTime='14:30'
End
Else If CONVERT (time, GETDATE()) <= '14:30:00' Begin
Set #fromDate=DATEADD(day,-1,CONVERT (date, GETDATE())) --yesterday
Set #fromTime='22:30'
End
Else If CONVERT (time, GETDATE()) <= '22:30:00' Begin
Set #fromDate=CONVERT (date, GETDATE()) --today
Set #fromTime='06:30'
End
Else Begin -- time > 22:30
Set #fromDate=CONVERT (date, GETDATE()) --today
Set #fromTime='14:30'
End
-- for testing only, show the values
Select #fromDate, #fromTime
I leave any remaining question(s) to your own solution

Check hours from one day to another in tsql

I have a table, which has columns to store the start time and end of the service (I do not have date and time, only the day of the week). I have to check if a time is available for the week, considering that a service starts on Monday and ends on Tuesday. Can someone help me?
CREATE TABLE #Calendar (
Name VARCHAR(100),
DayWeek INT,
HourStart TIME,
HourEnd TIME
);
INSERT INTO #Calendar (Name, DayWeek, HourStart, HourEnd)
VALUES ('Make a Cake', 1, '19:00:00', '07:00:00');
INSERT INTO #Calendar (Name, DayWeek, HourStart, HourEnd)
VALUES ('Make a cookie', 1, '07:00:00', '19:00:00');
INSERT INTO #Calendar (Name, DayWeek, HourStart, HourEnd)
VALUES ('Make a cookie', 2, '19:00:00', '23:00:00');
OK, this must work. It shows every line which has a time conflict; if you uncomment the last where it will show lines without conflict too
declare #test_DateTimeStart datetime=dateadd(day,4,'20:00:00') -- Check from Monday 20:00
declare #test_DateTimeEnd datetime=dateadd(day,5,'20:00:00') -- Check to Tuesday 20:00
select q2.result,c.*
from
#Calendar c
cross apply
( select
dateadd(day,DayWeek,convert(datetime,HourStart)) as DateTimeStart,
dateadd(day,DayWeek+1,convert(datetime,HourEnd)) as DateTimeEnd
)q
cross apply (select
case when exists
(
select 1 from #Calendar c2 where
(#test_DateTimeStart>DateTimeStart and #test_DateTimeStart<DateTimeEnd)
or
(#test_DateTimeEnd >DateTimeStart and #test_DateTimeEnd <DateTimeEnd)
)
then 'Time is taken due to this row -->'
else 'Time is free due to this row -->'
end as result
)q2
--where result='Time is taken due to this row -->'
This will solve it. It will not be able to use index because it uses calculation on columns when comparing:
DECLARE #from time = '22:59', #to time = '23:01'
DECLARE #DayWeek int = 2
;WITH CTE as
(
SELECT
dateadd(d, #DayWeek, cast(#from as datetime)) startdate,
dateadd(d,
CASE WHEN #to < #from
THEN #DayWeek + 1
ELSE #DayWeek
END,
cast(#to as datetime)) enddate
)
SELECT CASE WHEN
not exists
(
SELECT *
FROM #Calendar c
WHERE cte.startdate < dateadd(d, CASE WHEN HourEnd < HourStart
THEN DayWeek + 1 ELSE DayWeek END, cast(HourEnd as datetime))
AND cte.enddate > dateadd(d, DayWeek, cast(HourEnd as datetime))
) THEN 'Available' ELSE 'Not available' END
FROM CTE
Use below code to get the current day of week real time. then compare with your save data
var myHttpWebRequest = (HttpWebRequest)WebRequest.Create("http://www.google.com");
var response = myHttpWebRequest.GetResponse();
string todaysDates = response.Headers["date"];
return DateTime.ParseExact(todaysDates,"ddd, dd MMM yyyy HH:mm:ss'GMT'",CultureInfo.InvariantCulture.DateTimeFormat,DateTimeStyles.AssumeUniversal).DayOfWeek;

Showing dates by day wise, and having default date based on condition

am attaching a query to bring dates to a field,
if system time is before 01:00 pm then it should bring today date+1 else if system date is after or equal 01:00 pm it should bring today date +2
further , user can see the query result that will show him a date range along side with day names , and select one of them manually if the above cases wasn't what the user is looking for .
queries are avilable and working fine but separately,
one query bring date range , and one query set the date based on a condition , i need to make them one query , that bring the date ranges and set default date to be based on the conditions;
here are the queries :
Note : Q No 2 , I tried to make both queries as one query but its not bring the correct result , it keep bring today date +1 no matter what system time is.
1)
If DATEPART(Hour,Getdate())<12
SELECT GetDate()+1
If DATEPART(Hour,Getdate())>=12
SELECT GetDate()+2
2)
If DATEPART(Hour,Getdate())<12
DECLARE #Date1 DATE, #Date2 DATE
SET #Date1 = GetDate()+0
SET #Date2 = GetDate()+365
SELECT DATEADD(DAY,number+1,#Date1) [Date], DateName(Weekday,DATEADD(DAY,number+1,#Date1)) as dayname
FROM master..spt_values
WHERE type = 'P'
AND DATEADD(DAY,number+1,#Date1) < #Date2
If DATEPART(Hour,Getdate())>=12
DECLARE #Date3 DATE, #Date4 DATE
SET #Date3 = GetDate()+2
SET #Date4 = GetDate()+365
SELECT DATEADD(DAY,number+1,#Date3) [Date], DateName(Weekday,DATEADD(DAY,number+1,#Date3)) as dayname
FROM master..spt_values
WHERE type = 'P'
AND DATEADD(DAY,number+1,#Date3) < #Date4
I've used a CTE to calculate the start date. The CTE uses a CASE statement to tell if it is being run before or after 12.
WITH Base AS
(
/* Returns the start date based on the current time.
* Before midday the start date is today.
* After midday it is the day after tomorrow.
*/
SELECT
CASE
-- Use current time to calculate start date.
WHEN DATEPART(HOUR, GETDATE()) < 12 THEN DATEADD(DAY, 0, GETDATE())
ELSE DATEADD(DAY, 2, GETDATE())
END AS StartDate
)
SELECT
DATEADD(DAY, sv.Number + 1, b.StartDate) AS [Date],
DATENAME(WEEKDAY, DATEADD(DAY, sv.Number + 1, b.StartDate)) AS [DateName]
FROM
master..spt_values AS sv
CROSS JOIN Base AS b
WHERE
sv.[type] = 'P'
AND DATEADD(DAY, Number + 1, b.StartDate) < DATEADD(YEAR, 1, b.StartDate)
;

How to find the total playing time per day for all the users in my sql server database

I have a table which contains following columns
userid,
game,
gameStarttime datetime,
gameEndtime datetime,
startdate datetime,
currentdate datetime
I can retrieve all the playing times but I want to count the total playing time per DAY and 0 or null if game not played on a specific day.
Take a look at DATEDIFF to do the time calculations. Your requirements are not very clear, but it should work for whatever you're looking to do.
Your end result would probably look something like this:
SELECT
userid,
game,
DATEDIFF(SS, gameStarttime, gameEndtime) AS [TotalSeconds]
FROM [source]
GROUP BY
userid,
game
In the example query above, the SS counts the seconds between the 2 dates (assuming both are not null). If you need just minutes, then MI will provide the total minutes. However, I imagine total seconds is best so that you can convert to whatever unit of measure you need accurate, such as hours that might be "1.23" or something like that.
Again, most of this is speculation based on assumptions and what you seem to be looking for. Hope that helps.
MSDN Docs for DATEDIFF: https://msdn.microsoft.com/en-us/library/ms189794.aspx
You may also look up DATEPART if you want the minutes and seconds separately.
UPDATED BASED ON FEEDBACK
The query below breaks out the hour breakdowns by day, splits time across multiple days, and shows "0" for days where no games are played. Also, for your output, I have to assume you have a separate table of users (so you can show users who have no time in your date range).
-- Define start date
DECLARE #BeginDate DATE = '4/21/2015'
-- Create sample data
DECLARE #Usage TABLE (
userid int,
game nvarchar(50),
gameStartTime datetime,
gameEndTime datetime
)
DECLARE #Users TABLE (
userid int
)
INSERT #Users VALUES (1)
INSERT #Usage VALUES
(1, 'sample', '4/25/2015 10pm', '4/26/2015 2:30am'),
(1, 'sample', '4/22/2015 4pm', '4/22/2015 4:30pm')
-- Generate list of days in range
DECLARE #DayCount INT = DATEDIFF(DD, #BeginDate, GETDATE()) + 1
;WITH CTE AS (
SELECT TOP (225) [object_id] FROM sys.all_objects
), [Days] AS (
SELECT TOP (#DayCount)
DATEADD(DD, ROW_NUMBER() OVER (ORDER BY x.[object_id]) - 1, #BeginDate) AS [Day]
FROM CTE x
CROSS JOIN CTE y
ORDER BY
[Day]
)
SELECT
[Days].[Day],
Users.userid,
SUM(COALESCE(CONVERT(MONEY, DATEDIFF(SS, CASE WHEN CONVERT(DATE, Usage.gameStartTime) < [Day] THEN [Day] ELSE Usage.gameStartTime END,
CASE WHEN CONVERT(DATE, Usage.gameEndTime) > [Day] THEN DATEADD(DD, 1, [Days].[Day]) ELSE Usage.gameEndTime END)) / 3600, 0)) AS [Hours]
FROM [Days]
CROSS JOIN #Users Users
LEFT OUTER JOIN #Usage Usage
ON Usage.userid = Users.userid
AND [Days].[Day] BETWEEN CONVERT(DATE, Usage.gameStartTime) AND CONVERT(DATE, Usage.gameEndTime)
GROUP BY
[Days].[Day],
Users.userid
The query above yields the output below for the sample data:
Day userid Hours
---------- ----------- ---------------------
2015-04-21 1 0.00
2015-04-22 1 0.50
2015-04-23 1 0.00
2015-04-24 1 0.00
2015-04-25 1 2.00
2015-04-26 1 2.50
2015-04-27 1 0.00
I've edited my sql on sql fiddle and I think this might get you what you asked for. to me it looks a little more simple then the answer you've accepted.
DECLARE #FromDate datetime, #ToDate datetime
SELECT #Fromdate = MIN(StartDate), #ToDate = MAX(currentDate)
FROM Games
-- This recursive CTE will get you all dates
-- between the first StartDate and the last CurrentDate on your table
;WITH AllDates AS(
SELECT #Fromdate As TheDate
UNION ALL
SELECT TheDate + 1
FROM AllDates
WHERE TheDate + 1 <= #ToDate
)
SELECT UserId,
TheDate,
COALESCE(
SUM(
-- When the game starts and ends in the same date
CASE WHEN DATEDIFF(DAY, GameStartTime, GameEndTime) = 0 THEN
DATEDIFF(HOUR, GameStartTime, GameEndTime)
ELSE
-- when the game starts in the current date
CASE WHEN DATEDIFF(DAY, GameStartTime, TheDate) = 0 THEN
DATEDIFF(HOUR, GameStartTime, DATEADD(Day, 1, TheDate))
ELSE -- meaning the game ends in the current date
DATEDIFF(HOUR, TheDate, GameEndTime)
END
END
),
0) As HoursPerDay
FROM (
SELECT DISTINCT UserId,
TheDate,
CASE
WHEN CAST(GameStartTime as Date) = TheDate
THEN GameStartTime
ELSE NULL
END As GameStartTime, -- return null if no game started that day
CASE
WHEN CAST(GameEndTime as Date) = TheDate
THEN GameEndTime
ELSE NULL
END As GameEndTime -- return null if no game ended that day
FROM Games CROSS APPLY AllDates -- This is where the magic happens :-)
) InnerSelect
GROUP BY UserId, TheDate
ORDER BY UserId, TheDate
OPTION (MAXRECURSION 0)
Play with it your self on sql fiddle.

SQL - Sum of minutes between two timestamps by month

I am looking for an SQL query for the sum of minutes between start and end date for a particular month.
Eg.
I'm looking for the amount of minutes used in February.
Start Date Time: 27-02-13 00:00:00
End Date Time: 05-03-13 00:00:00
Because im only looking for the sum of february it should only give me the sum of 3 days (in minutes) and not the extra 5 days going into march.
I have no way to validate it but it should looks like:
SELECT DATEDIFF(minute, startDate, CASE when endDate > EOMONTH(startDate) THEN EOMONTH(startDate) ELSE endDate END) FROM ...
GL!
I left it in steps to illustrate each process. You can of course easily collapse this down, but I'll leave it up to you to do that.
Here's my solution http://www.sqlfiddle.com/#!3/b4991/1/0
SELECT *
, DATEDIFF(minute, StartDAte, NewEndDate) AS TotalMinutes
FROM
(
SELECT *
, CASE WHEN TempDate > EndDate THEN EndDate ELSE TempDate END AS NewEndDate -- Either EOM or old EndDate, whichever is smaller
FROM
(
SELECT *
, DATEADD(month, 1, CAST(Year + '-' + Month + '-1' AS DATETIME)) AS TempDate -- first day of the next month
FROM
(
select *
, CAST(DATEPART(month, StartDate) AS char(2)) AS Month
, CAST(DATEPART(year, StartDate) AS char(4)) AS Year
from tbl
) t0
) t1
) t2
First I get the year and month from the original StartDate. I then construct a first-of-the-month date from that. I then add one month to that to get me the first-of-the-month of the next month. Then I check if that new date is > or < the previous EndDate. I take the smaller of the two dates. Then I use the original StartDate and whichever is smaller between the TempDate and EndDate to determine my total minutes.
See Also EOMONTH: http://msdn.microsoft.com/en-us/library/hh213020.aspx
Look into using DATEDIFF -- this will just help you to get started:
SELECT DATEDIFF(minute, starttime, endtime)
http://msdn.microsoft.com/en-us/library/ms189794.aspx
To get the last day of the start month, use DATEADD:
SELECT DATEADD(second,-1,DATEADD(month, DATEDIFF(month,0,starttime)+1,0))
SQL Fiddle Demo
I recently had to solve a similar problem, I added two new functions to help with this:
CREATE FUNCTION [dbo].[GREATESTDATE]
(
-- Add the parameters for the function here
#Date1 DATETIME,
#Date2 DATETIME
)
RETURNS DATETIME
AS
BEGIN
IF (#Date1 < #Date2)
RETURN #Date2
ELSE
RETURN #Date1
END
and...
CREATE FUNCTION [dbo].[LEASTDATE]
(
-- Add the parameters for the function here
#Date1 DATETIME,
#Date2 DATETIME
)
RETURNS DATETIME
AS
BEGIN
IF (#Date1 > #Date2)
RETURN #Date2
ELSE
RETURN #Date1
END
Then use them like:
DATEDIFF(D,dbo.GREATESTDATE(#StartDate1,#StartDate2),dbo.LEASTDATE(#EndDate1,#EndDate2))