How to add Floating(decimal) hour in DateTime's DATEADD function? - sql

I am trying to add some hours in SQL SERVER using DATEADD function. But when I try this,
SELECT DATEADD(Hour, 0.5, GETDATE())
It is not adding 0.5 hour. How to solve this?

You can't. It's well describer on documentation: DATEADD (Transact-SQL)
number
Is an expression that can be resolved to an int that is added
to a datepart of date. User-defined variables are valid.
If you specify a value with a decimal fraction, the fraction is truncated and
not rounded.
UPDATE
You could try that:
SELECT DATEADD(Second, 0.5 * 60 * 60, GETDATE())
Of course - you can change DATEPART and multiplier to get desired precision.

You can't add parts of hours, just full hours. Use minute for half an hour
SELECT DATEADD(minute, 30, GETDATE())

I have found another approach to this where adding a number to the date instead of using the function works for fractions. For example:
GETDATE() + n
where n is the number of days. For 1 half hour, you can use:
GETDATE() + 0.5/24

Related

DATEADD in JDBC template

I'm trying a query select with jdbc and spring boot,
I want select informations where my creation date value is LESS than now minus 30.
I tried like this :
SELECT *
FROM informations
WHERE lastTreatment < DATEADD(MINUTE, -30, GETDATE())
I have an error like this :
Caused by: org.springframework.jdbc.BadSqlGrammarException: StatementCallback; bad SQL grammar
Anyone has idea ? Thanks
You claim Oracle but looks like you write MS SQL Server or MySQL. There is no such function DATEADD in Oracle and neither is there a GETDATE function. To add x days in to a date in just do date+x. In this case you just need a fractional part of a day, so just add an x which yields the need fraction. For 30 minuets that would be 30/(60*24) or (30 minuets/ (60 minuets per hour * 24 hours per day). As for GETDATE just use SYSDATE.
So your query becomes:
SELECT *
FROM informations
WHERE lastTreatment < sysdate-(30/(60*24));
maybe missing ; at the end?
SELECT *
FROM informations
WHERE lastTreatment < DATEADD(MINUTE, -30, GETDATE());

round GETDATE (SQL Server)

I have a function which is working fine in MySQL
round((now()-ts/60) as tdiff
(round the result of subtracting the current datetime from ts (also a datetime) divided by 60)
Attempting (and failing) to convert this for SQL Server.
Tried -
round((GETDATE()-ts/60) as tdiff
but that results in round function requires 2 or 3 parameters (which to me it does), so modified to -
round((GETDATE()-ts/60,0) as tdiff
but that results in the datatypes (GETDATE and ts) are incompatible in the subtract operator.
So then I attempted to cast both GETDATE and ts as date and that made no difference.
ts is a conventional datetime i.e.
2918-04-20 11:05:09 and I assumed GETDATE returned the same format.
As an example if GETDATE is today and ts is 2018-04-20 11:05:09 then tdiff is
6850891 (round effectively removes the dashes and colons and concatenates the datetime producing 20180420110509 for 2018-04-20 11:05:09 and 20180831164000 for 2018-08-31 16:40:00 and then divides by 60 to get 6850891.
Is there a remedy for this?
Regards, Ralph
GETDATE(), as per the documentation, returns a datetime. A datetime is accurate to 1/300 of a second, and it's accuracy cannot be changed.
If you want the time accurate to a second, you need to convert to a datetime2(0):
SELECT CONVERT(datetime2(0),GETDATE());
Also, however, don't use syntax like GETDATE()-ts. use the functions DATEADD and DATEDIFF for date maths.
I've no idea what GETDATE()-ts/60 is trying to acheive. Perhaps the number of minutes between the 2? DATEDIFF counts the "ticks" between 2 dates/times, thus DATEDIFF(MINUTE,'00:00:59','00:01:00') would return 1, despite there only being 1 second between the 2 times. This is because the minute value has "ticked" once (from 0 to 1). Therefore you might want to use DATEDIFF(SECOND,'00:00:59','00:01:00') / 60. This would return 0, as 1 / 60 in integer math is 0 (as is 59 / 60).
I think you want to use the DATEDIFF function:
DATEDIFF ( datepart , startdate , enddate )
DATEDIFF ( second, ts, GETDATE())
DATEDIFF ( second, ts, GETDATE())
DATEDIFF ( minute, ts, GETDATE())
DATEDIFF ( hour, ts, GETDATE())
The first argument tells it which increment of time to return.
If you are trying to find the difference between two values, then use datediff(). For instance:
select datediff(day, getdate(), ts)
gets the difference in days.
date_diff() or a related function would also be the right approach in MySQL.
sorry, I don't know if I have understand the question, you need to do date-date/60 and round the result?
In this case you have to change the minus ("-") with the DATEDIFF("Type return example DAYS", GETDATE(), ts).
So you will have ROUND((DATEDIFF(DAY,GETDATE(),ts)/60,0)
Please try and let me know if it will works for you
Bye

Rounding a datetime value down to the nearest half hour

I have a requirement to round a datetime2 value down to the nearest half hour. For example '10/17/2013 12:10:00.123' would round down to '10/17/2013 12:00:00.0' And '10/17/2013 12:34:17.123' would round down to 10/17/2013 12:30:00.0'. My first thought was to create a UDF which would break the date and time apart and do it that way. However, I'm wondering if something like this can be done in a single T-SQL statement?
I'm using SQL Server 2012 and the data type of the column is a dateTime2 (which cannot be converted to a float!!)
The answer by Ian is good, but it contains an unnecessary conversion. I suggest
SELECT CONVERT(smalldatetime, ROUND(CAST([columnname] AS float) * 48.0,0,1)/48.0) FROM [tableName]
If you want to round to the nearest half-hour instead of always rounding down, use
SELECT CONVERT(smalldatetime, ROUND(CAST([columnname] AS float) * 48.0,0)/48.0) FROM [tableName]
How about this
declare #d datetime = '2013-05-06 12:29.123'
select
case
when datepart(minute, #d) < 30 then cast(dateadd(minute, -datepart(minute,#d)-datepart(second,#d), #d) as smalldatetime)
when datepart(minute, #d) >= 30 then cast(dateadd(minute, -datepart(minute,#d)-datepart(second,#d)+30, #d) as smalldatetime)
end
Here is one way to do it:
update t set
d = dateadd(minute,datediff(minute,'19000101',d)/30*30,'19000101');
select cast(floor(cast(
cast('10/17/2013 12:34:00' as datetime)
as float(53)) * 48) / 48 as datetime)
EDIT
Works better if you use smalldatetime to avoid the extra precision
select cast(floor(cast(
cast('2012-01-02 11:33:14.097' as smalldatetime)
as float(53)) * 48) / 48 as smalldatetime)
Here is a slightly different approach that I used when I needed to round down to the nearest 5 minute interval. There is probably a way to simplify this further, but at least this got me what I needed.
DECLARE #now datetime = GETDATE()
SELECT #now as cur_datetime, DATEADD(MINUTE, -(DATEDIFF(MINUTE,DATEADD(HOUR,DATEDIFF(HOUR,0,#now), 0),DATEADD(MINUTE,DATEDIFF(MINUTE,0,#now), 0)) % 5), DATEADD(MINUTE,DATEDIFF(MINUTE,0,#now), 0)) as round_down_to_nearest_5_minute_mark
#Twinkles's answer works well in SQL server to round to closest half an hour.
However, in development, strongly recommend use FLOOR to round to last half an hour.
SELECT CONVERT(datetime, FLOOR(CAST([columnname] AS float) * 48.0)/48.0) FROM [tableName]
You can use DATETIME2FROMPARTS to reconstruct the date. To round the minutes down to 30 minute intervals use the formula minutes intdiv 30 * 30
SELECT
dt2,
DATETIME2FROMPARTS(
DATEPART(year, dt2),
DATEPART(month, dt2),
DATEPART(day, dt2),
DATEPART(hour, dt2),
DATEPART(minute, dt2) / 30 * 30,
0,
0,
0
)
FROM (VALUES
-- generic datetime2
(SYSDATETIME()),
-- 30 minute boundary
('2001-01-01 00:29:59.9999999'),
('2001-01-01 00:30:00.0000000'),
('2001-01-01 00:30:00.0000001'),
-- min and max date
('0001-01-01 00:00:00.0000000'),
('9999-12-31 23:59:59.9999999')
) AS v(dt2)

How to only check the time on datetime fields but ignore the date?

I have a column that stores data in datetime format. I want to check for all instances where the time part of this column is not equal to 00:00:00:000 - the date does not matter.
Basically, if time() was a function, something like this:
SELECT *
FROM progen.DY
WHERE TIME(DY_DATE) <> '00:00:00:000'
How do I go about doing this?
You only need a minor tweak on what you already have.
SELECT *
FROM progen.DY
WHERE TIME(DY_DATE) <> '00:00:00:000'
Use CONVERT to change your DATETIME to a TIME.
SELECT *
FROM progen.DY
WHERE CONVERT(TIME, DY_DATE) <> '00:00:00:000'
Another way is to convert it to different datatype, eg
SELECT *
FROM progen.DY
WHERE CAST(DY_DATE as float) - CAST(DY_DATE as int) > 0
SQLFiddle Demo
I do this all the time when trying to see if a table's column should be turned into a date instead of a datetime, which is really the answer.
select *
from progen.dy
where cast(dy_date as Date) <> dy_date
the cast removes the time and datetime has higher precedence, so when compared, if the are unequal then it has a time value. Same thing could be done with a cast to time, with a bit of different syntax.
Use DATEDIFF and DATEADD to instead get the date part of the datetime. Compare the column against the date only, and it will return those rows that have a non-zero time.
The way this works is that we first calculate the difference (in days) between the epoch and the value. We add that number to the epoch to create a new datetime. Since the result of DATEDIFF is an integer, any time component gets rounded off.
SELECT *
FROM Table
WHERE DateColumn <> DATEADD(d, DATEDIFF(d, 0, DateColumn), 0)
The time function could then be implemented by the following, not that I recommend it for this specific scenario:
SELECT DATEDIFF(minute, DATEADD(d, DATEDIFF(d, 0, DateColumn), 0), DateColumn) as MinutesIntoDay,
-- or, if you require higher precision
DATEDIFF(second, DATEADD(d, DATEDIFF(d, 0, DateColumn), 0), DateColumn) as MinutesIntoDay
FROM Table
Edit: As mentioned in other answers, you can cast to DATE to achieve the same effect as DATEADD(d, DATEDIFF(d, 0, DateColumn), 0), which cleans up nicely. However, DATE was only added in SQL Server 2008, whereas the formula has compatibility back to at least SQL 2000. So if you need the backwards compatibility or are dealing with SQL CE, casting to DATE is unavailable.
SELECT *
FROM progen.DY
WHERE CONVERT(TIME, DY_DATE - CONVERT(DATE, DY_DATE)) > '00:00'

How to convert Time to Decimal in SQL with an integer

I am having a couple of issues converting time to decimal...
Essentially I have used a DATEDIFF to identify the hours and minutes between two dates and times. This produces a result of 5.45, however I would like to get the result as 5.75.
select RTRIM(DATEDIFF(second, startdate, enddate)/3600)+'.'
+ RIGHT('0'+RTRIM((DATEDIFF(second, startdate, enddate) % 3600)/60),2)
from time
I have tried a few things but I believe the issue is that this is not an integer and that's why i cant convert the minutes.
Get the time difference in minutes, and divide by 60, this will place hours before the decimal separator and minutes after:
datediff(minute, startdate, enddate) / 60.0
Select DATEDIFF(second, startdate, enddate)/3600.0
As mentioned in this answer, "Take the DateDiff in seconds instead, and then divide by 86400.0. The decimal point is required."