SQL datediff function resulted in an overflow - sql

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?

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

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:
Can intime ever be null? If so how and why? I am assuming intime can never be null
I am assuming that if outtime 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.
Another strategy to handle 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

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.

Related

How can I find exact number of minutes without rounding between two dates in sql server

I am new to Sql server, I tried datediff several times but failed. All I need is the exact or precise number of minutes including fraction between two dates. E.g if the gap between two datetime fields is 40 seconds than it gives me 0.67 minutes and not 1 minute. Please help.
Take the difference in seconds and divide by 60.0:
select datediff(second, date1, date2) / 60.0 as diff_in_minutes
This should be close enough for most work. If you really want, you could use milliseconds instead of seconds.
select datediff(millisecond, date1, date2) / 60000.0 as diff_in_minutes
To get MILLISECOND accurate value
DECLARE #D1 DATETIME = '2015-04-16 21:38:02.610'
DECLARE #D2 DATETIME = '2015-04-16 21:38:29.023'
SELECT DATEDIFF(MILLISECOND, #D1, #D2)* 1.000 / ((1.66667) * POWER(10,5))
RESULT: 0.158477683044633910732

How to Sum (Time(n)) in Sql Server?

How want to use the sum of the time(n) operator so that i can calculate the overall total of the time but Sql server saying can't add the Time(n) column
i have a casted column which contain difference of two dates, and being casted as Time(n) by me. Now i want to add those column to get how much time i had used in total How much hours minute and seconds so i apply
select Sum(cast ((date1-date2) as Time(0))) from ABC_tbl
where date1 is reaching time and date2 is startingtime in Date format and i want to total of all hours
Convert the time to an integer value before you sum it (for example, seconds):
SELECT SUM(
datediff(second, '00:00:00', [TimeCol])
)
FROM
...
Replace [TimeCol] with the name of the Time(n) column. This gives you the total time in seconds, which you can then easily convert to minutes, hours, etc...
Hope this example help you.
DECLARE #A TABLE (SD TIME(0),ED TIME(0))
INSERT INTO #A VALUES
('09:01:09','17:59:09'),
('09:08:09','16:10:09'),
('08:55:05','18:00:00')
SELECT SUM(DATEDIFF(MINUTE,SD,ED)) SUM_IN_MINUTES,
SUM(DATEDIFF(HOUR,SD,ED)) SUM_IN_HOURS
FROM #A
Result:
SUM_IN_MINUTES | SUM_IN_HOURS
---------------------------------------
1505 | 25
select Sum(DATEDIFF(Minute,date1,date2)) AS TIME from ABC_tbl
u have to calculate the date difference with DATEDIFF function then use SUM function to calculate your sum of time.
you can change Minute to Second-Hour-month etc..
Try this:
DECLARE
#MidnightTime TIME = '00:00:00.0000000',
#MidnightDateTime DATETIME2 = '0001-01-01 00:00:00.0000000';
SELECT SumOfTime = DATEADD(SECOND, SUM ( DATEDIFF(SECOND, #MidnightTime, x.Col1) ), #MidnightDateTime)
FROM (VALUES
(1, CONVERT(TIME, '10:10:10.0000001')),
(2, CONVERT(TIME, '00:00:05.0000002')),
(3, CONVERT(TIME, '23:59:59.0000003'))
) x(ID, Col1)
/*
SumOfTime
---------------------------
0001-01-02 10:10:14.0000000 = 1 day (!), 10 hours, 10 minutes, 14 seconds
*/
Note: instead of SECOND you could use another precision: MINUTE, HOUR or ... NANOSECOND (see section Arguments > datepart). Using a higher precision could leads to Arithmetic overflow errors (use CONVERT(BIGINT|NUMERIC(...,0), ...).
Note #2: because the precision is SECOND the result (SumOfTime) has 0000000 nanoseconds.

Select DATEADD minutes with query SQL Server 2005

SELECT
[NAMENO],
[FIRSTNAME],
[MIDNAME],
[LASTNAME],
[SEX],
[STATUSOF],
[RELEASEDT],
CONVERT(VARCHAR(10), DOBDT, 101) AS DOBDT
FROM
database
WHERE
ReleaseDT >= dateadd(minute,datediff(minute,60,GETDATE()),0)
AND ReleaseDT < dateadd(minute,datediff(minute,0,GETDATE()),0)
I am wanting to get anyone that has a "releasedt" in the past 60 mins if that makes of sense? right now its pull the last 60 days..
Any suggestions??
It's just:
where ReleaseDT >= dateadd(minute, -60, getdate())
and ReleaseDT <= getdate()
Nesting dateadd and datediff (like you did in your code in the question) is not necessary.
In fact, datediff calculates the difference (in hours, minutes...whatever) between two datetime values, so you don't need it at all when you just want to get "now minus 60 minutes".

Easier way to compare a DATE field to the date value of GETDATE?

I have a field in a table Event.EventDate and it's of the data type DATE rather than DATETIME and then I have a view that has the following WHERE clause:
WHERE e.EventDate >= CAST(CONVERT(VARCHAR(MAX), GETDATE(), 101) AS DATETIME)
As you can see, I'm just trying to get all events >= today's date. The above code works, but it's ugly. I tried this ...
WHERE e.EventDate >= CONVERT(VARCHAR(MAX), GETDATE(), 101)
... and this ...
WHERE e.EventDate >= CONVERT(DATETIME, GETDATE(), 101)
... but those didn't work, they gave me every event > today's date. However, even if the above worked, it's still ugly.
Isn't there a better way?
Try:
WHERE e.EventDate >= cast(getdate() as date)
To cast getdate() into a date time. It's a clean way in SQL Server 2008 and up to strip out the time portion of a datetime type.
Using Shan Plourde's method is certainly cleaner and quicker, but for the more general case when you want to round a datetime to a particular time interval, I use
dateadd(dd,datediff(dd,0,[datetime column]),0)
where dd stands for day, and can be replaced with mm (month), hh (hour), mi (minute), and probably others.
If you want to get fancy and round to, say, 15 minute intervals, you can use
dateadd(mi,
-datepart(mi,[datetime column])%15,
dateadd(mi,datediff(mi,0,[datetime column]),0)
)
where % is the modulo operator. You'll get wacky results for this if you don't use an interval that divides 60 evenly.

DateDiff in SQL Server asking for help

I am using SQL Server 2008. I have a table which has a datetime type column called CreateTime. I need to select all the records from this table whose CreateTime is more than 3 days and half an hour from current time (UTC time). I am using T-SQL store procedure.
BTW: The CreateTime column is some time in the past time.
I have taken quite some time to learn and search for help from MSDN for DateDiff, but cannot figure out. Could anyone show me a sample please?
thanks in advance,
George
You can select and add a WHERE clause with a DATEDIFF using minutes:
SELECT (fields)
FROM (table)
WHERE
DATEDIFF(MINUTE, CREATETIME, getutcdate()) <= (3*24*60 + 30)
And of course, if you only wants those rows which are MORE than 3 days and 30 minutes away, just use the opposite:
WHERE
DATEDIFF(MINUTE, CREATETIME, getutcdate()) > (3*24*60 + 30)
A sample:
SELECT
DATEDIFF(MINUTE, '2009-08-01 08:00:00', getutcdate()),
DATEDIFF(MINUTE, '2009-07-31 20:00:00', getutcdate()),
DATEDIFF(MINUTE, '2009-07-23 20:00:00', getutcdate())
gives as result:
96 816 12337
So the first two dates are still within your 4350 minute bracket (less than 3 days and 30 minutes ago), while the third date is further away.
Marc
You need DATEADD:
WHERE DATEADD(minute, 4350, CreateTime) <= getutcdate()
Or, as you mentioned, you can use DATEDIFF:
WHERE DATEDIFF(minute, CreateTime, getutcdate()) <= 4350
(4350 is '3 days and 30 minutes' in minutes)
One minor quibble with the given answers, though they are correct. Don't apply the function to the column: apply the function to the comparison value.
If CREATETIME is indexed then it's a scan rather than seek with the function on the column.
You don't need millions of rows for this to be a problem.
Adapting the answer of marc_s:
SELECT (fields)
FROM (table)
WHERE
CREATETIME <= DATEADD(MINUTE, - (3*24*60 + 30), getutcdate())