Reputation: 53
I am calculating TotalHours
of a employee worked in office based on Intime
and Outtime
resultant in the form of hh.mm
like 8.30
.
So, I wrote below sql query :
SELECT EMPLOYEEID, sum(DateDiff(mi,isnull(In_Time,0),isnull(Out_Time,0))/60) +
sum(round(DateDiff(mi,isnull(In_Time,0),isnull(Out_Time,0))%60,2))/100.0 +
sum(round(DateDiff(ss,isnull(In_Time,0),isnull(Out_Time,0)),2))/10000.0 as
TotalHours from HR_EMPLOYEES
The above sql server query was running correctly intially, but now it is giving following exception:
java.sql.SQLException: The datediff function resulted in an overflow. The number of
dateparts separating two date/time instances is too large. Try to use datediff with a
less precise datepart.
Could anybody please help me to get rid off of this?
Upvotes: 1
Views: 9607
Reputation: 14002
Is it not easier to just discard the null values (returning datediff in seconds from a datetime of zero is what's probably overflowing your query) and also use 'hh' for datediff
? Or are you also looking for the number of minutes (do you NEED seconds?? If this is for timesheets etc, seconds don't really matter do they?)
SELECT
EMPLOYEEID,
CASE
WHEN In_Time IS NOT NULL AND Out_Time IS NOT NULL THEN sum(DateDiff(hh, In_Time, Out_Time))
ELSE 0
END as TotalHours
FROM HR_EMPLOYEES
Edit: ok for hours/minutes just use:
SELECT
EMPLOYEEID,
CASE
WHEN In_Time IS NOT NULL AND Out_Time IS NOT NULL THEN sum(DateDiff(mi, In_Time, Out_Time)) / 60.0
ELSE 0
END as TotalHours
FROM HR_EMPLOYEES
This gives you hours plus a fraction of minutes (so 90 minutes = 1.5 hours)
Edit2: if you want minutes as actual minutes and not a fraction use this:
SELECT
EMPLOYEEID,
CASE
WHEN In_Time IS NOT NULL AND Out_Time IS NOT NULL THEN
sum(DateDiff(hh, In_Time, Out_Time) + -- Total hours
DateDiff(mi, In_Time, Out_Time) % 60 * .01) -- Total minutes (divided by 100 so that you can add it to the hours)
ELSE 0
END as TotalHours
FROM HR_EMPLOYEES
Upvotes: 2
Reputation: 3752
You may try this:
select empid,
convert(varchar(5), sum(datediff(minute, [intime], isnull([outtime], dateadd(hh, 19, DATEADD(dd, DATEDIFF(dd, 0, [intime]), 0))))) / 60)
+ ':' +
convert(varchar(5),sum(datediff(minute, [intime], isnull([outtime], dateadd(hh, 19, DATEADD(dd, DATEDIFF(dd, 0, [intime]), 0))))) % 60)
as TotalHours
from HR_EMPLOYEES group by empid
Some thoughts:
intime
ever be null? If so how and why? I am assuming intime
can never be nullouttime
is null
then, the employee is still working, thus the use of getdate()
But it may also be the case that there was a software bug that caused the null
.null
in outtime
could be to make it the midnight of the intime
day. Then this begs the question, how the next day will be handled.I think there may be a lot of edge cases here. You will have to be careful.
EDIT: Modified outtime
to 7 PM of intime
day if outtime
is null as per OP's comment. Used Best approach to remove time part of datetime in SQL Server
Upvotes: 1
Reputation: 239704
Instead of using 0
as your default/fixed point in time, use some other constant date instead, that's closer to the values you're going to be processing - and thus less likely to produce an overflow.
0
gets implicitly converted to midnight on 01/01/1900. A better constant might be, for instance, 01/01/2000:
SELECT EMPLOYEEID, sum(DateDiff(mi,isnull(In_Time,'20000101'),isnull(Out_Time,'20000101'))/60) +
sum(round(DateDiff(mi,isnull(In_Time,'20000101'),isnull(Out_Time,'20000101'))%60,2))/100.0 +
sum(round(DateDiff(ss,isnull(In_Time,'20000101'),isnull(Out_Time,'20000101')),2))/10000.0 as
TotalHours from HR_EMPLOYEES
Although the more I look at this, the more I'm unsure that defaulting the date to any value even makes sense.
Upvotes: 0