Convert smallint to time - sql

I am trying to convert a smallint to a time format.
I am using SQL Server 2005 which doesn't support the time datatype.
I am storing the time as 1400 which is a smallint. When retrieving I want it to be converted to a time format. Such as 14:00
Any ideas or guidance on the matter. If there is an easier way to do it or if the way I am trying is possible?

You can get a result as varchar by using this:
SELECT
RIGHT('0' + CONVERT(varchar(10), yourTime / 100), 2) + ':' +
RIGHT('0' + CONVERT(varchar(10), yourTime % 100), 2) As timeString
FROM
yourTable
You can also have a result in DATETIME format like this:
SELECT
CONVERT(datetime, CONVERT(varchar(10), yourTime / 100)+ ':' + CONVERT(varchar(10), yourTime % 100))
FROM
yourTable
In SQL Server 2012+ you can have a result in time format:
SELECT
TIMEFROMPARTS(yourTime / 100, yourTime % 100, 0, 0, 0) As timeFormat
FROM
yourTable

Related

Converting numeric(17,9) into a datetime

In a data warehouse, I am building I am receiving DateTime data from one of our sources in numeric(17,9) format. Is there a way in SQL Server to convert the numeric to a DateTime and whilst retaining the time information? For example, a date such as 20210928.110424000 should be converted to 2021-09-28 11:04:24:000. I am able to convert this to 2021-09-28 00:00:00.000 but as you can see I am missing the time information.
The most performant way to do this is probably to use DATETIMEFROMPARTS with arithmetic, rather than using string manipulation.
SELECT
DATETIMEFROMPARTS(
CAST(#date AS int) / 10000,
CAST(#date AS int) / 100 % 100,
CAST(#date AS int) % 100,
CAST(#date * 100 AS int) % 100,
CAST(#date % 0.01 * 10000 AS int),
CAST(#date % 0.0001 * 1000000 AS int),
CAST(#date % 0.000001 * 1000000000 AS int)
)
db<>fiddle
A small matter with STUFF(). You only need to be concerned with the time portion... yyyymmdd will convert to a date.
Example
Declare #V numeric(17,9) = 20210928.110424000
Select try_convert(datetime,stuff(stuff(stuff(stuff(#V,16,0,'.'),14,0,':'),12,0,':'),9,1,' '))
Results
2021-09-28 11:04:24.000
Another way to do it, using substring would be:
declare #date numeric(17,9) = 20210928.110424000
-- mask 2021-09-28 11:04:24.000 (121)
select
convert(datetime,
substring(convert(varchar(20),#date),1,4) + '-' +
substring(convert(varchar(20),#date),5,2) + '-' +
substring(convert(varchar(20),#date),7,2) + ' ' +
substring(convert(varchar(20),#date),10,2) + ':' +
substring(convert(varchar(20),#date),12,2) + ':' +
substring(convert(varchar(20),#date),14,2) + '.' +
substring(convert(varchar(20),#date),16,3)
,121)
You can test on this db<>fiddle
Nevertheless, in traditional BI environments, the dates used to be linked to date/time dimensions (with surrogate keys numeric), rather than date/datetime. This strategy allows you to group the data from the dimension, where for a given surrogate key (i.e. YYYYMMDD) you have any other attributes associated (year, quarter, semester, month, week, ...).

Convert from bigint to time only

I have big-int data, and I want to convert it from Big-int to just time, for example I have this value 53006745 for ' 14hrs 43min '
Please help me to write the query in SQL Server, so that will convert big-int into minutes.
If You're looking Pure Time you could try below SQL Query which will give Minutes from Your Integer Value:
DECLARE #value INT = 53006745
SELECT DATEPART(MINUTE, DATEADD(s, CONVERT(BIGINT, #value) / 1000, CONVERT(DATETIME, '1-1-2017 00:00:00'))) [Minutes];
Result :
Minutes
43
You can use this code for yourself in SQL :
SELECT DATEADD(s, CONVERT(BIGINT, 53006745 ) / 1000,
CONVERT(DATETIME,
'1-1-1970 00:00:00'))
This code return 1970-01-01 14:43:26.000 as you like
DECLARE #Value INT = 53006745
SELECT
CONVERT(VARCHAR, #Value/3600000) + ':' -- Hours
+ RIGHT('0' + CONVERT(VARCHAR, #Value%3600000/60000), 2) + ':' -- Minutes
+ RIGHT('0' + CONVERT(VARCHAR, #Value%3600000%60000/1000), 2) + '.' -- Seconds
+ RIGHT('00' + CONVERT(VARCHAR, #Value%1000), 3) -- Milliseconds

How do I convert time into an integer in SQL Server

I have a date column and a time column that are integers
I converted the date portion like this
select convert(int, convert(varchar(10), getdate(), 112))
I thought I could do the same with this query that gives the time in HH:mm:ss
SELECT CONVERT(VARCHAR(8), GETDATE(), 108)
How do I convert just the time into an integer?
This should convert your time into an integer representing seconds from midnight.
SELECT (DATEPART(hour, Col1) * 3600) + (DATEPART(minute, Col1) * 60) + DATEPART(second, Col1) as SecondsFromMidnight FROM T1;
Assuming you are looking for the "time" analogy to the "date" portion of your code which takes YYYYMMDD and turns it into an INT, you can:
start with the HH:mm:ss format given by the style number 108
remove the colons to get that string into HHmmss
then convert that to INT
For example:
SELECT REPLACE(
CONVERT(VARCHAR(8), GETDATE(), 108),
':',
''
) AS [StringVersion],
CONVERT(INT, REPLACE(
CONVERT(VARCHAR(8), GETDATE(), 108),
':',
''
)
) AS [IntVersion];
You can use the differece between midnight and the time of the day. For example, using getdate(), you can know the percentage of the time of the day with this query:
select convert(float,getdate()-convert(date,getdate()))
You can then convert this number to seconds
select convert(int,86400 * convert(float,getdate()-convert(date,getdate())))
You'll get the number of seconds from midnight
I think this is easier to understand when using with a SQL Update statement.
UPDATE dbo.MyTable
SET TIME_AS_INT = CAST(REPLACE(CAST(CONVERT(Time(0), GETDATE()) AS varchar),':','') AS INT)
To add/subtract time from the result before converting use dateadd()
SELECT CAST(REPLACE(CAST(CONVERT(Time(0), dateadd(MINUTE, 1, getdate())) AS varchar),':','') AS INT)

SQL conversion from varchar to datetime

One of the columns of my SQL Server table is mm:ss of varchar type where mm = minutes and ss = seconds.
I need to get the average of that column.
Should I convert that column to datetime format first? If so can you tell me how? If not can you tell me what I should do?
Here is my failed attempt to convert it to datetime :
SELECT CONVERT(DATETIME, '2014-01-01 '+Pace+':00', 108)
Where pace is a varchar like 23:05
If you want the average, I would convert the column to number of seconds and work with that:
select avg(pace_secs) as average_in_seconds
from (select cast(left(pace, 2) as int) * 60 + cast(right(pace, 2) as int) as pace_secs
from t
) t;
If you want this back in the format, then you can do:
select right('00' + cast(avg(pace_secs) / 60 as int), 2) + ':' +
right('00' + avg(page_secs) % 60), 2)
from (select cast(left(pace, 2) as int) * 60 + cast(right(pace, 2) as int) as pace_secs
from t
) t;
declare #pace varchar(20) = '23:05 ';
SELECT cast( '2014-01-01 '+cast(#pace as varchar(5))+':00' as datetime)
For SQL2012 and later
SELECT
FORMAT(DATEADD(second,AVG(DATEDIFF(second,0,'00:'+[Pace])),0),'mm:ss')
FROM MyTable

DATEDIFF in HH:MM:SS format

I need to calculate the total length in terms of Hours, Minutes, Seconds, and the average length, given some data with start time and end time.
For example the result must be something like 45:15:10 which means 45 hours 15 min 10 sec, or 30:07 for 30 min 07 sec.
We're using SQL Server 2008 R2 and the conversion failed when time is more than 24:59:59. Any idea of how I could do this?
For information, the columns in the table are Id, StartDateTime, EndDateTime, etc. I need to make a monthly report which contains the recordings count of the month, the total length of these records, and the average length. I'd like to know if there is an easy way to perform all of this.
You shouldn't be converting to time - it is meant to store a point in time on a single 24h clock, not a duration or interval (even one that is constrained on its own to < 24 hours, which clearly your data is not). Instead you can take the datediff in the smallest interval required (in your case, seconds), and then perform some math and string manipulation to present it in the output format you need (it might also be preferable to return the seconds to the application or report tool and have it do this work).
DECLARE #d TABLE
(
id INT IDENTITY(1,1),
StartDateTime DATETIME,
EndDateTime DATETIME
);
INSERT #d(StartDateTime, EndDateTime) VALUES
(DATEADD(DAY, -2, GETDATE()), DATEADD(MINUTE, 15, GETDATE())),
(GETDATE() , DATEADD(MINUTE, 22, GETDATE())),
(DATEADD(DAY, -1, GETDATE()), DATEADD(MINUTE, 5, GETDATE())),
(DATEADD(DAY, -4, GETDATE()), DATEADD(SECOND, 14, GETDATE()));
;WITH x AS (SELECT id, StartDateTime, EndDateTime,
d = DATEDIFF(SECOND, StartDateTime, EndDateTime),
a = AVG(DATEDIFF(SECOND, StartDateTime, EndDateTime)) OVER()
FROM #d
)
SELECT id, StartDateTime, EndDateTime,
[delta_HH:MM:SS] = CONVERT(VARCHAR(5), d/60/60)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), d/60%60), 2)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), d % 60), 2),
[avg_HH:MM:SS] = CONVERT(VARCHAR(5), a/60/60)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), a/60%60), 2)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), a % 60), 2)
FROM x;
Results:
id StartDateTime EndDateTime delta_HH:MM:SS avg_HH:MM:SS
-- ------------------- ------------------- -------------- ------------
1 2013-01-19 14:24:46 2013-01-21 14:39:46 48:15:00 42:10:33
2 2013-01-21 14:24:46 2013-01-21 14:46:46 0:22:00 42:10:33
3 2013-01-20 14:24:46 2013-01-21 14:29:46 24:05:00 42:10:33
4 2013-01-17 14:24:46 2013-01-21 14:25:00 96:00:14 42:10:33
This isn't precisely what you asked for, as it won't show just MM:SS for deltas < 1 hour. You can adjust that with a simple CASE expression:
;WITH x AS (SELECT id, StartDateTime, EndDateTime,
d = DATEDIFF(SECOND, StartDateTime, EndDateTime),
a = AVG(DATEDIFF(SECOND, StartDateTime, EndDateTime)) OVER()
FROM #d
)
SELECT id, StartDateTime, EndDateTime,
[delta_HH:MM:SS] = CASE WHEN d >= 3600 THEN
CONVERT(VARCHAR(5), d/60/60) + ':' ELSE '' END
+ RIGHT('0' + CONVERT(VARCHAR(2), d/60%60), 2)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), d % 60), 2),
[avg_HH:MM:SS] = CASE WHEN a >= 3600 THEN
CONVERT(VARCHAR(5), a/60/60) + ':' ELSE '' END
+ RIGHT('0' + CONVERT(VARCHAR(2), a/60%60), 2)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), a % 60), 2)
FROM x;
This query changes the delta column in the 2nd row in the above result from 0:22:00 to 22:00.
I slightly modified Avinash's answer as it may end with error if difference is too big. If you need only HH:mm:ss it is sufficient to distinguish at seconds level ony like this:
SELECT CONVERT(time,
DATEADD(s,
DATEDIFF(s,
'2018-01-07 09:53:00',
'2018-01-07 11:53:01'),
CAST('1900-01-01 00:00:00.0000000' as datetime2)
)
)
SELECT CONVERT(time,
DATEADD(mcs,
DATEDIFF(mcs,
'2007-05-07 09:53:00.0273335',
'2007-05-07 09:53:01.0376635'),
CAST('1900-01-01 00:00:00.0000000' as datetime2)
)
)
If you want to do averages, then the best approach is to convert to seconds or fractions of a day. Day fractions are convenient in SQL Server, because you can do things like:
select avg(cast(endtime - starttime) as float)
from t
You can convert it back to a datetime using the reverse cast:
select cast(avg(cast(endtime - starttime as float) as datetime)
from t
The arithmetic to get the times in the format you want . . . that is a pain. You might consider including days in the final format, and using:
select right(convert(varchar(255), <val>, 120), 10)
To get the hours exceeding 24, here is another approach:
select cast(floor(cast(<val> as float)*24) as varchar(255))+right(convert(varchar(255), <val>, 120), 6)
It uses convert for minutes and seconds, which should be padded with 0s on the left. It then appends the hours as a separate value.
Starting in SQL SERVER 2012, you don't need to use DATEDIFF function. You can use FORMAT function to achieve what you want:
SELECT
FORMAT(CONVERT(TIME, [appoitment].[Start] - [appointment].[End]), N'hh\:mm') AS 'Duration'
FROM
[tblAppointment] (NOLOCK)
A way that avoids overflows and can include days and go all the way to milliseconds in the output:
DECLARE #startDate AS DATETIME = '2018-06-01 14:20:02.100'
DECLARE #endDate AS DATETIME = '2018-06-02 15:23:09.000'
SELECT CAST(DATEDIFF(day,'1900-01-01', #endDate - #startDate) AS VARCHAR) + 'd ' + CONVERT(varchar(22), #endDate - #startDate, 114)
The above will return
1d 01:03:06:900
And, off course, you can use the formatting of your choice
SQL Supports datetime substraction which outputs a new datetime relative to the MIN date (for instance 1900-01-01, you can probably get this value from some system variable) This works better than DATEDIFF, because DATEDIFF will count ONE for each "datepart boundaries crossed", even if the elapsed time is less than a whole datapart. Another nice thing about this method is that it allows you to use the date formatting conversions.
If days is the (positive) number of days, like 0.5 for 12 hours, use this expression to format it as a proper duration:
CONVERT(varchar(9), FLOOR(days * 24)) + RIGHT(CONVERT(char(19), CAST(days AS datetime), 120), 6)
Excel will understands values up to 9999:59:59 when pasted. There apply a custom format: [h]:mm:ss in the English version ([u]:mm:ss for Dutch).