SQL Server remove milliseconds from datetime - sql-server

select *
from table
where date > '2010-07-20 03:21:52'
which I would expect to not give me any results... EXCEPT I'm getting a record with a datetime of 2010-07-20 03:21:52.577
how can I make the query ignore milliseconds?

You just have to figure out the millisecond part of the date and subtract it out before comparison, like this:
select *
from table
where DATEADD(ms, -DATEPART(ms, date), date) > '2010-07-20 03:21:52'

If you are using SQL Server (starting with 2008), choose one of this:
CONVERT(DATETIME2(0), YourDateField)
LEFT(RTRIM(CONVERT(DATETIMEOFFSET, YourDateField)), 19)
CONVERT(DATETIMEOFFSET(0), YourDateField) -- with the addition of a time zone offset

Try:
SELECT *
FROM table
WHERE datetime >
CONVERT(DATETIME,
CONVERT(VARCHAR(20),
CONVERT(DATETIME, '2010-07-20 03:21:52'), 120))
Or if your date is an actual datetime value:
DECLARE #date DATETIME
SET #date = GETDATE()
SELECT CONVERT(DATETIME, CONVERT(VARCHAR(20), #date, 120))
The conversion to style 120 cuts off the milliseconds...

select * from table
where DATEADD(ms, DATEDIFF(ms, '20000101', date), '20000101') > '2010-07-20 03:21:52'
You'll have to trim milliseconds before comparison, which will be slow over many rows
Do one of these to fix this:
created a computed column with the expressions above to compare against
remove milliseconds on insert/update to avoid the read overhead
If SQL Server 2008, use datetime2(0)

Use CAST with following parameters:
Date
select Cast('2017-10-11 14:38:50.540' as date)
Output: 2017-10-11
Datetime
select Cast('2017-10-11 14:38:50.540' as datetime)
Output: 2017-10-11 14:38:50.540
SmallDatetime
select Cast('2017-10-11 14:38:50.540' as smalldatetime)
Output: 2017-10-11 14:39:00
Note this method rounds to whole minutes (so you lose the seconds as well as the milliseconds)
DatetimeOffset
select Cast('2017-10-11 14:38:50.540' as datetimeoffset)
Output: 2017-10-11 14:38:50.5400000 +00:00
Datetime2
select Cast('2017-10-11 14:38:50.540' as datetime2)
Output: 2017-10-11 14:38:50.5400000

For this particular query, why make expensive function calls for each row when you could just ask for values starting at the next higher second:
select *
from table
where date >= '2010-07-20 03:21:53'

Use 'Smalldatetime' data type
select convert(smalldatetime, getdate())
will fetch
2015-01-08 15:27:00

There's more than one way to do it:
select 1 where datediff(second, '2010-07-20 03:21:52', '2010-07-20 03:21:52.577') >= 0
or
select *
from table
where datediff(second, '2010-07-20 03:21:52', date) >= 0
one less function call, but you have to be beware of overflowing the max integer if the dates are too far apart.

One more way I've set up SQL Server queries to ignore milliseconds when I'm looking for events from a particular second (in a parameter in "YYYY-MM-DD HH:TT:SS" format) using a stored procedure:
WHERE
...[Time_stamp] >= CAST(CONCAT(#YYYYMMDDHHTTSS,'.000') as DateTime) AND
...[Time_stamp] <= CAST(CONCAT(#YYYYMMDDHHTTSS,'.999') as DateTime)
You could use something similar to ignore minutes and seconds too.

Please try this
select substring('12:20:19.8470000',1,(CHARINDEX('.','12:20:19.8470000',1)-1))
(No column name)
12:20:19

I'm very late but I had the same issue a few days ago. None of the solutions above worked or seemed fit. I just needed a timestamp without milliseconds so I converted to a string using Date_Format and then back to a date with Str_To_Date:
STR_TO_DATE(DATE_FORMAT(your-timestamp-here, '%Y-%m-%d %H:%i:%s'),'%Y-%m-%d %H:%i:%s')
Its a little messy but works like a charm.

May be this will help..
SELECT [Datetime] = CAST('20120228' AS smalldatetime)
o/p:
2012-02-28 00:00:00

Review this example:
declare #now datetimeoffset = sysdatetimeoffset();
select #now;
-- 1
select convert(datetimeoffset(0), #now, 120);
-- 2
select convert(datetimeoffset, convert(varchar, #now, 120));
which yields output like the following:
2021-07-30 09:21:37.7000000 +00:00
-- 1
2021-07-30 09:21:38 +00:00
-- 2
2021-07-30 09:21:37.0000000 +00:00
Note that for (1), the result is rounded (up in this case), while for (2) it is truncated.
Therefore, if you want to truncate the milliseconds off a date(time)-type value as per the question, you must use:
declare #myDateTimeValue = <date-time-value>
select cast(convert(varchar, #myDateValue, 120) as <same-type-as-#myDateTimeValue>);

Related

Convert a time calculation to time in HH:MM

I am looking to create a calculation in SQL Server that will display the time difference in HH_MM from a time column.
For example, the difference in hours and minutes between
5:45 PM - 3:30 PM = 2:15 (desired output)
The closest I have been able to get is this:
CONVERT(TIME,cals_END_time - cals_START_time) = 02:15:00.0000000
How do I go about 'trimming' it down to 2:15?
Assuming the columns are datetime, use the format function to format the time value:
select format(cast(cals_end_time - cals_start_time as time), N'h\:mm')
from (values
(cast('2022-07-07 15:30:00' as datetime), cast('2022-07-07 17:45:00' as datetime))
) as tests(cals_start_time, cals_end_time)
DB<>Fiddle
If you want to add/subtract dates/datetimes you need to use the relevant functions to do so as follows:
select *, convert(varchar(5), dateadd(minute, datediff(minute, [TimeOut], TimeIn), convert(time, '00:00'))) TimeDifference
-- , CONVERT(TIME, [TimeOut], TimeIn) -- gives an error anyway?
from (
values
(convert(time, '05:45 PM'), convert(time, '03:30 PM'))
) x (TimeIn, [TimeOut]);
Returns:
TimeIn
TimeOut
TimeDifference
17:45:00.0000000
15:30:00.0000000
02:15

How to convert a date with milliseconds into a date with just 000 instead of the milliseconds?

My incoming data contains a date in the following format:
2019-05-01 15:20:51.920
but after getting loaded into the target system it gets converted into the following :
2019-05-01 15:20:51.000
I would like to convert the source data and compare it with my target system since my target data is as per requirements.
ie 2019-05-01 15:20:51.920 should be converted to 2019-05-01 15:20:51.000
I am looking at convert functions as follows but it is only trimming the ms (using getdate(0 as a example):
select CONVERT(DATETIME2(3),getdate())
--2019-05-01 15:20:51.920
select CONVERT(DATETIME2(2),getdate())
--2019-05-01 15:20:51.92
Could someone tell me how I could achieve this? Thanks!
This should be also a more or less performant way:
SELECT GETDATE() AS OriginalValue
, CONVERT(DATETIME, CONVERT(VARCHAR(19), GETDATE(), 121)) ValueWithoutMilliseconds
The idea behind is to trim milliseconds, by cutting the last 4 characters of a fixed output format and then convert it back to a datetime
An output:
OriginalValue | ValueWithoutMilliseconds
----------------------------------------------------
2019-05-01 21:44:58.473 | 2019-05-01 21:44:58.000
Why not just cast the fractional seconds portion away using datetime2(0)?
declare #dateValue datetime2(3) = SysDateTime();
select Convert(datetime2(3), Convert(datetime2(0), #dateValue));
May be this should be give result what you are looking for,
DECLARE #TodayDatatime datetime
SET #TodayDatatime = DateAdd(DAY, DateDiff(DAY, 0, GetDate()), 0)
select GETDATE()
SELECT DateAdd(SECOND, DateDiff(SECOND, #TodayDatatime, GetDate()), #TodayDatatime)
Using the DATEADD/DATEDIFF method to truncate dates can work for this. Another option is to convert to datetime2(0).
SELECT DATEADD( SS, DATEDIFF(SS, '2020', aDate), '2020'),
CAST( aDate AS datetime2(0))
FROM (VALUES( CAST( '2019-05-01 15:20:51.920' AS datetime2(3))))x(aDate)
Note that the first option will truncate and the second one will round the value.

SQL Date-Time Conversion with nested converts experiences random conversion errors

Looking for assistance with a strange issue if anyone has ideas:
I have a SQL that statement works most of the time in a T-SQL script but crashes occasionally. I have identified the data that a crash occurs on and cannot identify any difference between data rows that work.
The goal of this code is to add the time to an already existing datetime value that has 00:00:00 as the time from the second time column (as outlined below). My goal is to combine both columns into YYYY-MM-DD HH:MM:SS format, but I had to convert them to char first to trim off the orignal 00:00:00.
Columns
LogDate - contains date only in DateTime format (YYYY-MM-DD HH:MM:SS)
LogTime - contains the time of the action and is in varchar format (HH:MM)
SQL Conversion
SELECT CONVERT(DATETIME, CONVERT(CHAR(8), LogDate, 112) + ' ' + CONVERT(CHAR(8), LogTime, 108))
FROM TestTable
WHERE EventSerial = '100001'
However, if I change the EventSerial in the above statement to a different row, such as '100002', the statement works.
The data for each row is below:
EventSerial 100001's values:
LogDate: 2015-04-02 00:00:00.000
LogTime: 10:04
EventSerial 100002's values:
LogDate: 2015-04-02 00:00:00.000
LogTime: 10:48
Running with data set 1 fails, running with data set 2 produces output. Also, running the code without the final datetime conversion works, or if I run the code with the string manually it works (as outlined below:)
SELECT CONVERT(CHAR(8), LogDate, 112) + ' ' + CONVERT(CHAR(8), LogTime, 108)
FROM TestTable
WHERE EventSerial = '100001'
SELECT CONVERT(DATETIME, '20150402 10:48')
SELECT CONVERT(DATETIME, '20150402 10:04')
Any suggestions, I'm sure its something silly that I'm missing (and I probably took the long way around the issue anyway. The desired output would be 2015-04-02 10:04:00
First, datetime has no format. (why?)
Second, you don't need to convert the datetime value to char to add hours and minutes, just use DateAdd:
SELECT DATEADD(Minute,
CAST(RIGHT(LogTime, 2) as int),
DATEADD(Hour,
CAST(LEFT(LogTime, 2) as int),
LogDate
)
)
FROM TestTable
WHERE EventSerial = '100001'
Also, note that convert does not hold a style for yyyymmdd hh:mm
Note: code was written directly here, there might be some mistakes.
I'm not sure why you're getting the error... possibly there are some unseen characters in your varchar time field... like a tab or something maybe? Try this query:
SELECT ascii(substring(LogTime,1,1)) Char1,
ascii(substring(LogTime,2,1)) Char2,
ascii(substring(LogTime,3,1)) Char3,
ascii(substring(LogTime,4,1)) Char4,
ascii(substring(LogTime,5,1)) Char5
FROM TestTable
WHERE EventSerial = '100001'
It should show these results:
Char1 Char2 Char3 Char4 Char5
----------- ----------- ----------- ----------- -----------
49 48 58 48 52
(1 row(s) affected)
This would be a bit more efficient:
select dateadd(minute, datediff(minute,0, LogTime), LogDate)
FROM TestTable
But this assumes that your date field always has 00:00:00 time information. If you want to be sure that is stripped out as well you could use:
select dateadd(minute, datediff(minute,0, LogTime), dateadd(day, datediff(day, 0, Logdate),0))
FROM TestTable

SQL Server Query - Selecting values BETWEEN 2 Dates

I am getting some problems in getting one query done.
I have 2 strings which are suppose to store time in this format (HH:mm Ex: Date1 -> '20:20' and Date2 -> '21:20'). I want to get the current time (CONVERT(VARCHAR(5),getdate(),108) -> to get only 'HH:mm') and get all rows that are between the current date.
The idea is: Select * where "getdate() between date1 and date2", this is not a query, only the idea.
Edit:
Time1 Time2
08:20 09:05
09:05 09:50
10:05 10:50
10:50 11:35
11:45 12:30
12:30 13:15
13:35 14:20
Thx for the solutions, I will check them, but one question how can i "fix" the problem when it's 9:05 (for example), I will get both rows/records, I assume i have to go to the seconds right?
The following constructs two DATETIMEs, based on TIME only, from your input strings (#TimeStr1 and #TimeStr2) then strips the DATE part from GETDATE(). Then you can easily do the query with BETWEEN.
DECLARE
#CurrentTime DATETIME,
#TimeStr1 VARCHAR(12),
#TimeStr2 VARCHAR(12),
#Time1 DATETIME,
#Time2 DATETIME
SET #TimeStr1 = '20:20'
SET #TimeStr2 = '21:20'
SET #Time1 = CAST('1900-01-01 ' + #TimeStr1 AS DATETIME)
SET #Time2 = CAST('1900-01-01 ' + #TimeStr2 AS DATETIME)
-- The following strips the date from datetime leaving only a time
SET #CurrentTime = DateAdd(ss, DateDiff(ss, DateAdd(dd, DateDiff(dd, 0, GetDate()), 0), GetDate()), 0)
SELECT * FROM YourTable WHERE #CurrentTime BETWEEN #Time1 AND #Time2
This will work for all versions of SQL SERVER. If you are using a version >= 2008 then a simpler version of the above exists.
If you are worried about overlaps (eg your "09:05" problem) use the following query that avoids the problem by using > and <= rather then BETWEEN
SELECT * FROM YourTable WHERE #CurrentTime > #Time1 AND #CurrentTime <= #Time2

Select records created in a 24 hour time-frame

I'm trying to query our database to find all records that were created between 6am yesterday and 6am today. This will be run in a report at any point during the day so set times/dates are useless.
I have this so far:-
SELECT * FROM DaySummaryDetail DSD
WHERE DSD.FromDateTime BETWEEN DATEADD(DAY, -1, GetDate())
AND DATEADD(Day, 1, GetDate())
But obviously this only works for 24 hours ago from right now until right now. I can't figure out how to apply a time as well as date.
Every example I find online seems slightly different and uses set dates/times ie, >= 20/02/2015 06:00:00.
I normally use Oracle SQL which would simply work using this:-
ptt.mod_date_time >= TRUNC (SYSDATE - 1) - 2 / 24
AND ptt.mod_date_time <= TRUNC (SYSDATE - 1) + 22 / 24
This would return results from 10pm to 10pm but the format appears totally different in SQL Server.
You can get the datetime values you are after by doing the following:
SELECT DATEADD(HOUR,6,CONVERT(DATETIME, CONVERT(DATE ,GETDATE()))) Today6AM,
DATEADD(HOUR,-18,CONVERT(DATETIME, CONVERT(DATE ,GETDATE()))) Yesterday6AM
By doing this: CONVERT(DATE ,GETDATE()) you are stripping off the time portion of today's date. Converting it back to datetime gives you midnight for today.
The query adds 6 hours to midnight of the current day for 6am today and subtracts 18 hours from midnight of the current day to give you 6am on the previous day.
Output:
Today6AM Yesterday6AM
================================================
2015-02-20 06:00:00.000 2015-02-19 06:00:00.000
So adding that to your query:
SELECT *
FROM DaySummaryDetail DSD
WHERE DSD.FromDateTime
BETWEEN DATEADD(HOUR,-18,CONVERT(DATETIME, CONVERT(DATE ,GETDATE())))
AND DATEADD(HOUR,6,CONVERT(DATETIME, CONVERT(DATE ,GETDATE())))
DECLARE #StartTimestamp datetime
DECLARE #EndTimestamp datetime
DECLARE #HourPartOfSearchRange nvarchar(6)
SET #HourPartOfSearchRange = ' 06:30'
SET #StartTimestamp =
CAST((CONVERT(varchar(11), DATEADD(DAY,-1,#CurrentUTCDateTime), 106) + #HourPartOfSearchRange) AS datetime)
SET #EndTimestamp =
CAST((CONVERT(varchar(11), #CurrentUTCDateTime, 106) + #HourPartOfSearchRange) AS datetime)
SELECT * FROM dbo.Test Where Timestamp Between #StartTimestamp AND #EndTimestamp
today 6am is
dateadd(hour,6,cast(cast(getdate() as date) as datetime))
cast(getdate() as date) truncates the timepart, cast it back as datetime because dateadd won't add hours otherwise and add 6hours
One solution would be like so:
select *
from DaySummaryDetail DSD
where DSD.FromDateTime between cast(cast(cast(getdate()-1 as date) as varchar(30)) + ' 06:00:00.000' as datetime)
and cast(cast(cast(getdate() as date) as varchar(30)) + ' 06:00:00.000' as datetime)
This should help ...
SELECT DATEADD( hour, 6, CAST(CAST(GETDATE(), AS Date) AS DateTime) ) AS 'Today#6am'
SELECT DATEADD( hour, 6, CAST(CAST(GETDATE()-1, AS Date) AS DateTime) ) AS 'Yesterday#6am'
In SQL Server 2012 you can use SMALLDATETIMEFROMPARTS to construct a datetime value that is today at 6am like this:
SMALLDATETIMEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), DAY(GETDATE()), 6, 0)
Output: 2015-02-20 06:00:00
then you can use the above expression in place of GETDATE() in the WHERE clause:
DECLARE #TodayAt6AM DATETIME = SMALLDATETIMEFROMPARTS(YEAR(GETDATE()),
MONTH(GETDATE()),
DAY(GETDATE()),
6,
0)
SELECT *
FROM DaySummaryDetail DSD
WHERE DSD.FromDateTime BETWEEN DATEADD(DAY, -1, #TodayAt6AM) AND
DATEADD(Day, 1, #TodayAt6AM)

Resources