SQL Server convert varchar hh:mm:ss to time - sql

Is there a way to convert varchar 'hh:mm:ss' format data to time to allowing summing?

DECLARE #InX VARCHAR(10)='09:08:23'
SELECT CAST(#InX AS TIME(0))

You can convert those values to time and for summing you could simply get their difference in seconds from midnight and sum. Result would be in seconds. ie:
DECLARE #times TABLE(t TIME(0));
INSERT INTO #times(t)VALUES('03:20:30'), ('02:10'), ('01:00');
SELECT SUM(DATEDIFF(SECOND, '00:00:00', t))FROM #times AS t;

Related

Average Time on SQL

I am working on a report where I need to find the average amount of time between two timestamps.
To find the time between the time stamps I used:
CAST(( Time2 - Time1 ) as time(0)) AS 'Time Between Stage1 and Stage2'
Now that I have that column, I am trying to get the Average Time Spent Between Stage1 and Stage2. I'm looking for the output to be in the hh:mm:ss format.
Try this:
Format(AVERAGE(CAST(( Time2 - Time1 ) as time(0)), "HH:MM: SS"))
declare #t1 datetime, #t2 datetime
set #t1 = '14:15:54'
set #t2 = '15:12:33'
select #t1,#t2
select cast(dateadd(ms, AVG(datediff( ms, #t1 ,#t2 )), '00:00:00') as time)
First, find the difference using DateDiff in the format of the lowest grain.
Then, find the average
Convert the Average back to date using the DateAdd (you will get errors if you try to use a cast or convert)
Finally, Cast back to a time
replace the variables with your attributes

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)

To subtract two dates without Using DateAdd Function or DateDiff Function

How i got this output, can you please explain the reason behind it?
declare #a datetime = '2017-06-08 16:02:22.467',
#b datetime = '2017-10-23 00:00:00.000'
select DAY(#a - #b)
select #a - #b
Output:
17
1899-08-17 16:02:22.467
Disclaimer: The information in this answer is relevant only to the DateTime data type. It doesn't apply to the newer data types (DateTime2 , Date and Time).
Well, dates in sql server are stored as the number of days since 1900-01-01.
You can see it if you run this query:
SELECT CAST(0 as datetime)
You'll get 1900-01-01 00:00:00 as the result.
Time is stored as the number of ticks since midnight.
There are 300 ticks per second.
Since the date in #a is before the date in #b, you get a negative result for the date (-137), and that number is then added to 01-01-1900 to give you 1899-08-17. The time in #a is after the time in #b, and since the time in #b is midnight, you get the time of #a in the result.
declare #a datetime = '2017-06-08 16:02:22.467',
#b datetime = '2017-10-23 00:00:00.000'
select datediff(day, #a, #b)
it returns 137, so difference between these two days are 137.
declare #c as datetime = null;
select isnull(#c, 0)
it return 1900-01-01 00:00:00.000, it means the default value for the datetime is 1900-01-01 00:00:00.000
In your case this select #a-#b minus operation is subtracting the actual difference of 137 days with the default value.
select dateadd(day, -137, '1900-01-01 00:00:00.000')
it returns 1899-08-17 00:00:00.000
if it is select #b-#a, it will return 1900-05-17 07:57:37.533 i.e, it will add 137 days from the default value.
and DAY() function simply returns the day of the given date.
So for the 1899-08-17 the DAY() should be 17
Well when you substracting 2 dates zero value for datetime type is 1900-01-01 00:00:00.00.
But from SQL 2008 microsoft created new type datetime2 and as far as you get overflow (negative value) in here it casts result to datetime2 that statrs from 0001-01-01 00:00:00.00
DAY function only get date part from your datetime or datetime2 type.
This will subtract the two date and will add it to Minimum Date in SQL which is '1900-01-01 00:00:00.000'. So after subtracting both dates and getting the difference, it will add it in subsequent minimum date which is '1900-01-01 00:00:00.000'.

Calculate the time after converting into a new datatype

Goal:
To display data with this list:
Hour
-----
2
2,5
1
Problem:
Is it any possibiltiy to convert column StartTime and EndTime into specific datatype and then doing a calculacution of X1- X2
CREATE TABLE Data
(
StartTime VARCHAR(5),
EndTime VARCHAR(5),
)
GO
INSERT INTO Data(StartTime,EndTime)
SELECT '10:00','12:00' UNION ALL
SELECT '13:30','16:00' UNION ALL
SELECT '14:00','15:00' UNION ALL
GO
EDITED: To get mins in decimals
SELECT ROUND(CAST( Mins AS FLOAT)/60,2) AS [hour]
FROM (
SELECT DATEDIFF(minute, CAST(StartTime AS TIME),CAST(EndTime AS TIME)) AS Mins
FROM Data
) A
SELECT DATEDIFF(mi, CONVERT(DATETIME, StartTime), CONVERT(DATETIME, EndTime))
/ 60.0 AS Hour
FROM Data
It work's for your example data, but you should check if EndTime could be the next day, like:
StarTime: 22:30
EndTime: 01:20
Is that escenario possible? If it is, you must store the date for both Start and End times, not only the hour.
If you are using SQL-SERVER 2008, then why not just use the time object. You could then run the appropriate time comparison functions. If not, you can still make it work by converting to a datetime and running comparison functions. I believe a convert with just a time to a datetime will result in the date as the minimum date.

mysql: searching BETWEEN dates stored as varchar

i would like to select * from table where dates between (some_date and another_date)
the problem is that the dates are stored as varchar!
here are examples of dates that i have:
7/29/2010 9:53 AM
7/16/2010 7:57:39 AM
please notice that some records have seconds and some do not
i dont care about the time at all i just need the date
reporttime is the date field
this is not working:
SELECT * FROM batchinfo
where cast(reporttime as date) between ('7/28/10' and '7/29/10')
this:
SELECT * from batchinfo WHERE reporttime BETWEEN STR_TO_DATE(7/28/2010, '%m/%/d/%Y %h:%i:%s %p')
AND STR_TO_DATE(7/29/2010, '%m/%/d/%Y %h:%i:%s %p')
is returning:
Truncated incorrect datetime value: '7/8/2010 11:47 AM'
Incorrect datetime value: '0.00012009' for function str_to_date
this:
SELECT * from batchinfo WHERE STR_TO_DATE(reporttime, '%m/%/d/%Y %h:%i:%s %p') BETWEEN STR_TO_DATE(7/28/2010, '%m/%/d/%Y')
AND STR_TO_DATE(7/29/2010, '%m/%/d/%Y')
is returning:
Incorrect datetime value: '7/8/2010 11:47 AM' for function str_to_date
OMG PONIES:
i am taking everything before the first blank:
SELECT * from batchinfo WHERE STR_TO_DATE(LEFT(reporttime,LOCATE(' ',reporttime)), '%m/%/d/%Y') BETWEEN STR_TO_DATE(7/28/2010, '%m/%/d/%Y')
AND STR_TO_DATE(7/29/2010, '%m/%/d/%Y')
and now i get this returned:
Incorrect datetime value: '7/8/2010' for function str_to_date
You want to search between dates, store them as dates. By storing them as strings you're shooting yourself in the foot.
You'd basically need to extract date part from the string (using SUBSTR() or LEFT() ) and parse it to date format (using STR_TO_DATE()).
The performance of such solution will be appaling.
STR_TO_DATE(LEFT(reporttime,LOCATE(' ',reporttime)),'%m/%d/%Y') BETWEEN '2010-07-28' AND '2010-07-29'
Use STR_TO_DATE to convert the strings to the DateTime data type. The format shorthand is found under DATE_FORMAT:
STR_TO_DATE(column, '%m/%/d/%Y %h:%i:%s %p')
The problem is, you'll have to update the VARCHAR dates to all be the same format first, before you can use:
WHERE STR_TO_DATE(reporttime, '%m/%/d/%Y %h:%i:%s %p') BETWEEN STR_TO_DATE(some_date, '%m/%/d/%Y')
AND STR_TO_DATE(another_date, '%m/%/d/%Y')
Date formats are not consistent (some use hyphens, others slashes and Year/Month/day order can be totally different...), so STR_TO_DATE is the most accommodating & consistent means of turning a string into a DateTime. Only after the value is DateTime, does Date/Time functionality become available like DATE() to get only the date portion...
Because of the data type change, an index on some_date & another_date columns can not be used.
IF you are using SQl use this query
Data
DECLARE #Dates TABLE (StartDate varchar(100));
INSERT INTO #Dates VALUES ('7/1/2010 9:10 AM');
INSERT INTO #Dates VALUES ('7/5/2010 10:33 AM');
INSERT INTO #Dates VALUES ('7/13/2010 04:53 AM');
INSERT INTO #Dates VALUES ('7/22/2010 8:45 AM');
INSERT INTO #Dates VALUES ('7/10/2010 11:20 AM');
INSERT INTO #Dates VALUES ('7/11/2010 12:40 AM');
Query:
SELECT * FROM #Dates
WHERE (CONVERT(datetime,StartDate,101) >= CONVERT(datetime,'7/1/2010 9:10 AM',101))
AND (CONVERT(datetime,StartDate,101) <= CONVERT(datetime,'7/15/2010 9:10 AM',101))
ORDER BY CONVERT(datetime,StartDate,101)
You can CAST your varchar values to DATETIME or DATE type.
WHERE CAST(dates AS DATE) BETWEEN (7/28/10 and 7/29/10)
This might not be an optimal solution, because you may lose the benefit that indexes provide.
This Date query will work perfectly...
Database 'Date' Will be like '01/01/2016' and datatype is 'varchar'
SELECT * FROM `test` WHERE STR_TO_DATE(`test`.`date`, '%d/%m/%Y') BETWEEN '2016-01-01' AND '2016-01-31' ORDER BY `test`.`date` ASC
If date is in Varchar
Query
AND c.sentdate > '2016-jun-15'