sql server: what's wrong with my date data? - sql

i have a column with dates, but it is a varchar:
8/31/2010 9:48
8/31/2010 9:49
8/31/2010 9:51
8/31/2010 9:52
8/31/2010 9:55
8/31/2010 9:59
8/31/2010 10:11
8/31/2010 10:13
8/31/2010 10:16
8/31/2010 10:37
8/31/2010 10:42
i made sure that none of these will be a BAD date:
SELECT *
FROM qcvalues.dbo.batchinfo
WHERE ISDATE(reporttime) <> 1
this returned 0 results
question:
i need to return dates between a certain range:
select rowid from qcvalues.dbo.batchinfo where CONVERT(DATE, Substring( reporttime, 1, LEN(reporttime)), 103)
between cast('2010-08-01' as datetime) and CAST('2010-08-31' as datetime)
and i am getting this error;
Msg 241, Level 16, State 1, Line 2
Conversion failed when converting date and/or time from character string.
what is wrong with my conversion?

If you need to store dates then use a datetime column in the future
does this work?
WHERE CONVERT(DATE,RTRIM(reporttime))
BETWEEN '2010-08-01' and '2010-08-31'
If not use SET DATEFORMAT MDY before running it
And if you have to store it in a varchar column then use YYYYMMDD format...that way you can do
WHERE reporttime like '201008%' if you want August 2010

This will solve your problem:
select rowid
from qcvalues.dbo.batchinfo
where
CONVERT(DATE, reporttime, 101) >= '20100801'
-- style 101, not 103
-- also notice date conversion invariant format YYYYMMDD with no separators
AND CONVERT(DATE, reporttime, 101) < '20100901'
-- using BETWEEN with an end date of '8/31/2010' will skip
-- times between '8/31/2010 00:00:00.003' and '8/31/2010 23:59:59.997'
Try this to see what the problem is:
select convert(datetime, '8/31/2010 9:48', 103)
select convert(datetime, '8/31/2010 9:48', 101)

put SET DATEFORMAT MDY before your query.

This will strip out the time portion too
select rowid
from qcvalues.dbo.batchinfo
Where cast(floor(cast(cast(reportTime as datetime)as float))as datetime)
between cast('2010-08-01' as datetime)
and cast('2010-08-31' as datetime)

Remember, this CAST('2010-08-31' as datetime) will have its time portion as 00:00.
Consider casting your varchar data as smalldatetime, and being specific about the boundaries of times in your between. No need to be converting, substring, etc. Just one CAST will do.
Consider this as a potential solution:
SELECT rowid from qcvalues.dbo.batchinfo
WHERE CAST(reporttime as smalldatetime)
BETWEEN '2010-08-01' AND '2010-08-31 23:59'

Related

SQL Server - Check if given date+time is between two datetime variables by exact date+time

I have two datetime columns in a DB table: #Start and #End.
Both columns contain the date and time, for example:
#Start: 2018-10-01 19:00:00
#End: 2018-10-10 23:59:00
I want to know if the current date is exactly between both datetimes considering the dates and the times.
So, 2018-10-08 16:37 and 2018-10-10 23:59:00 would match this range
and 2018-10-11 00:00:00 would not.
(In this case this date is one minute later than the End date, so it is not between my datetime range).
SELECT Id FROM Table1 WHERE GETDATE() BETWEEN Start AND End
I don't use GETDATE() in real code, I use an argument. The problem is that current date argument may contain seconds and milliseconds like 23:59:59.123. My code treats such date as not conforming given range. But I don't care about s/ms.
Is there a workaround?
Update:
The precision I want to achieve is in minutes. So I do not even need to take in account the seconds nor the milliseconds. The date time format I would be working on would be 'yyyy-MM-dd hh-mm' but I do not know how to use the BETWEEN clause converting the Start and End to the shown format so I can compare the dates.
You would seem to want this logic:
WHERE GETDATE() >= Start
AND GETDATE() < DATEADD(minute, 1, End)
Assuming that the time part of End is 23:59:00 it covers all possible values between 23:59:00 and 23:59:59.999...999.
SELECT Id FROM Table1 WHERE GETDATE() BETWEEN '2018-10-01 19:00:00' AND '2018-10-10 23:59:00'
TRY
SELECT Id FROM Table1 WHERE
CONVERT(varchar(16),GETDATE(),121) BETWEEN
CONVERT(varchar(16),[Start], 121)
AND
CONVERT(varchar(16),[END],121);
Example of rounding without strings
DECLARE #GetDateMinutes as datetime2;
DECLARE #X as datetime2 = getdate();
--round to minutes, could be made into a function
SET #GetDateMinutes = dateadd(minute,datepart(minute,#x),dateadd(hour, datepart(hour,#x),cast(CAST(#x as date) as datetime2)))
select #x, #GetDateMinutes
Truncate the seconds using the technique described here to avoid all string conversions, then just do your comparison. Here's a fully contained example that uses cross apply and values to encapsulate the truncation logic for start and end:
-- truncate minutes from current date time
declare #currentDateTime datetime2(0) = DateAdd(minute, DateDiff(minute, 0, Convert(datetime2(0), N'2018-10-01 23:58:32.912')), 0);
select #currentDateTime as CurrentDateTime
, a.*
from (values -- create a table of dummy values
(Convert(datetime2(3), N'2018-10-01 19:48:14.735'), Convert(datetime2(3), N'2018-10-10 02:00:00.000'))
, (Convert(datetime2(3), N'2018-10-01 22:43:19.532'), Convert(datetime2(3), N'2018-11-01 12:17:26.663'))
) as a (StartDateTime, EndDateTime)
cross apply (values(
-- truncate minutes from start date time
DateAdd(minute, DateDiff(minute, 0, Convert(datetime2(0), a.StartDateTime)), 0)
-- truncate minutes from end date time
, DateAdd(minute, DateDiff(minute, 0, Convert(datetime2(0), a.EndDateTime)), 0)
)) as b (StartDateTimeWithoutSeconds, EndDateTimeWithoutSeconds)
where #currentDateTime between b.StartDateTimeWithoutSeconds and b.EndDateTimeWithoutSeconds;
Your data appears to already have the s/ms truncated from start and end but figured I'd apply the same logic to all values involved just to be consistent. Here's the formula for stripping s/ms without all the "noise" from the example:
DateAdd(minute, DateDiff(minute, 0, Convert(datetime2(0), <SomeDateTime>)), 0)

How do I convert a datetime column in database from UTC to PST using SQL?

I have a database called dialogqa and table called dbo.devicelog with one of the column called LogDateTime in UTC DateTime format. I want to convert the UTC DateTime format into PST format.
However, I already have a Select query in the beginning and a result generated with the code:
Select * from DeviceLog where EnergyConsumed <= 10000 and LogDateTime between '2018-01-15' and '2018-01-18'
order by LogDateTime ASC;
Example Table
How can I merge the UTC -> PST code to the above so the final result shows the LogDateTime format -8 hours?
Sorry I'm new to SQL query and I hope the question makes sense.
Thanks,
You can use use DateAdd function: https://learn.microsoft.com/en-us/sql/t-sql/functions/dateadd-transact-sql
e.g.
Select *, dateadd(hour, -8, LogDateTime) from DeviceLog where EnergyConsumed <= 10000 and dateadd(hour, -8, LogDateTime) between '2018-01-15' and '2018-01-18'

How to subtract Time Column from DateTime Column in SQL?

I have Crea_Date column which is a DateTime Column. I want to subtract the value in the IST column from crea_date Column and return a new column with the DateTime Value in it. My sample data is like this:
States crea_date IST
AB 2014-12-30 15:01:00.000 12:30:00.0000000
AK 2014-12-29 16:32:00.000 10:30:00.0000000
AZ 2014-12-18 16:07:00.000 11:30:00.0000000
Thanks in Advance
As strange as it might seem, you can add/subtract datetime values and it seems it's "normal" behavior.
Internally, datetime values are stored as the offset from 1/1/1900. If I add 22/1/2015 and 1/1/2015 I get 22/1/2130 because the second value is actually 115 years after 1900.
When you cast a time value to datetime only the time component is copied and the date component is set to 1/1/1900. In effect, you have an interval equal to your original time value.
This way I can subtract 10:30 hours from a specific datetime:
declare #d datetime='2014-11-04 12:51:00', #t time='10:30:00'
select #d -cast(#t as datetime)
//-----------------------
//2014-11-04 02:21:00.000
This behavior isn't an implementation quirk - it is explicitly permitted only for the datetime type. All other datetime types (eg datetime2, datetimeoffset) return the error Operand data type datetimeoffset is invalid for subtract operator.
If IST is an integer number of seconds:
SELECT DATEADD(s, -IST, crea_date)
FROM yourTable
If IST is of the TIME type:
SELECT DATEADD(ms, DATEDIFF(ms, IST, '00:00:00'), crea_date)
FROM yourTable
Try the below if IST is a character based column.
SELECT
Crea_Date, IST,
dateadd(hh,cast(substring(IST,1,2) as int),
dateadd(mi, cast(substring(IST, 4,2) as int),
dateadd(s, cast(substring(IST,7,2 ) as int), crea_date)
)) Final_Date
from [Yourtable]
You will get the added date in Final_Date column.
With slight modification in #0xF Answer I found the final Solution:
convert(varchar(10),
DATEADD(ms, DATEDIFF(ms, '00:00:00', IST), crea_date), 101) + right(convert(varchar(32
DATEADD(ms, DATEDIFF(ms, '00:00:00', IST), crea_date),100),8)

How to assign current date with specific time to column?

How do i assign current date with a specific time?
let's say 8:00:00 AM to Column EXIT_DT of datatype datetime??
I have tried GETDATE() AS EXIT_DT but it gives me current datetime. I am using Sql server 2005. Any help?
Lets say Today is 1/3/2013 and i want my result to return as a datetime datatype with value 1/3/2013 8:00:00 AM. If i run the statement ytd, the result will be 1/2/2013 8:00:00 AM
This formula will always produce 08:00 for the day it is called, and avoids string manipulation:
select DATEADD(day,DATEDIFF(day,'20010101',GETDATE()),'2001-01-01T08:00:00')
Try to avoid solutions that convert to and from strings - treating datetime values as strings is one of the largest sources of bugs.
It works by computing the number of days (as an integer) that have elapsed since 1st January 2001. It then adds that same number of days to 08:00 on 1st January 2001.
You can try this :
DECLARE #dt datetime;
SET #dt=CONVERT(DateTime, CONVERT(VARCHAR,GETDATE(),101)+' 8:00:00')
SELECT CONVERT(VARCHAR, #dt, 101)+' '+ LTRIM(RIGHT(CONVERT(VARCHAR(20),#dt, 100), 7))
Visit http://www.sql-server-helper.com/tips/date-formats.aspx for datetime formats.
Use Convert along with getdate() to get specific formats.
ex:
SELECT CONVERT(VARCHAR(30),GETDATE(),113)
This is a bit stupid, but it works
select cast(cast(getdate() as date) as datetime) + '08:00:00'
it casts the getdate() to date thus losing the hours, than it casts it to datetime and adds 8 hours.
If you want to avoid implicit conversion of varchar to datetime, you could use this version:
select cast(cast(getdate() as date) as datetime)
+ convert(datetime,'08:00:00',114)
This is also working. (1). convert today's date to ISO format (yyyymmdd) (2). add the time, (3). convert back to datetime
Select convert(datetime, convert(varchar, getdate(),112) + ' ' + '8:00:00AM')
--Results
2013-01-03 08:00:00.000
If you need in specific format you need to convert back to varchar again.
-- AM/PM --
SELECT TO_CHAR(sysdate, 'MM/DD/YYYY HH:MI:SS AM') FROM dual
/
-- 24 hrs format --
SELECT TO_CHAR(sysdate, 'MM/DD/YYYY HH24:MI:SS') FROM dual
/

SQL datetime needs to read 00:00:00.000

I have the following piece of SQL:
select DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0))
which comes through as this format:
2012-02-29 23:59:59.000
I need the exact piece of code with the date the same, however the time part must read 00:00:00.000
Modify* I should have been clear here: I need to have the last day of previous month at any given time (with the time in 00:00:00.000 format of course)
select dateadd(d,datediff(d,0,dateadd(s,-1,dateadd(m,datediff(m,0,getdate()),0))),0)
SELECT DATEADD(MONTH, -1, DATEADD(DAY, 0, DATEDIFF(DAY, 0, GETDATE())))
This will give you the last second of the prior month
select dateadd(s,-1,dateadd(month,datediff(month,0,GETDATE()),0));
and this will give you the last day of the prior month
select dateadd(day,-1,dateadd(month,datediff(month,0,GETDATE()),0));
More details of how to do this:
select dateadd(day,datediff(day,0,#datetime),0);
or
select dateadd(day,datediff(day,0,GETDATE()),0);
In English: Take the number of days between this date and 0 and add those days to 0.
This works with any parameter for datediff. So
select dateadd(month,datediff(month,0,GETDATE()),0);
Will "remove" all day information in addition to time information.
An alternative method to strip out the time portion is to cast it to a float, apply the Floor function and cast back to a datetime.
select Cast(Floor(Cast(DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0)) as float)) as datetime)
SELECT DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0))
In SQL Server 2012 you could use eomonth.
SELECT EOMONTH(DATEADD(MONTH, -1, GETDATE()))
Saw some similar posts
select cast(cast(dateadd(dd,-1,getdate()) as date) as datetime)
Cast your dateadd as a date and then enclose it in another cast back to datetime
So it goes from this
2012-02-29 23:59:59.000
To this
2012-02-29
and the finally this
2012-02-29 00:00:00.000