This question already has answers here:
Most efficient method for adding leading 0's to an int in sql
(5 answers)
Closed 7 months ago.
I have date and time values that are stored (separately) as integers.
I now want to convert them into datetime data type into a new column but have trouble handling the time.
My first idea was to do it kinda like this (I can deal with the dates so in this example I'm just using a dummy date):
SET new_column = CAST(CONCAT('2020-01-01T',
date_column / 10000, ':',
date_column % 10000 / 100, ':',
date_column % 100) AS DATETIME)
The issue is that CAST expects exactly the format 'yyyy-mm-ddThh:mm:ss' but the calculation may sometimes only return one digit instead of the needed two digits for a part of the time.
For example the time one minute after 9am would result in the string '2020-01-01T9:1:0' though '2020-01-01T09:01:00' would be required.
Is there an efficient way to add leading 0s?
EDIT: The date_column contains integer values that represent times in the format hhmmss. So for example 10am would be stored as 100000, one minute after 9am would be stored as 90100.
I know that it is stupid to encode times/dates as integer. This is for legacy reasons and my current task is to fix it ;)
You need to pad with a zero to deal with single-digit output. Unfortunately, T-SQL doesn't have a PAD or RPAD function, so you have to do it manually:
SET new_column = CONVERT(datetime,
CONCAT('2020-01-01T',
RIGHT(CONCAT('0', date_column / 10000),2)
+ ':'
+ RIGHT(CONCAT('0', date_column % 10000 / 100), 2)
+ ':'
+ RIGHT(CONCAT('0', date_column % 100), 2)));
Example db<>fiddle
Instead of worrying about creating a string to be converted - convert the time to seconds and just add that to your date:
Declare #myDate int = 20220711
, #myTime int = 182233;
Select cast(#myDate As char(10))
, #myTime / 10000 * 60 * 60
, #myTime % 10000 / 100 * 60
, #myTime % 100
, dateadd(second, (#myTime / 10000 * 60 * 60) + (#myTime % 10000 / 100 * 60) + (#myTime % 100), cast(#myDate As char(10)))
Related
I have a set of integer value which can be either a single digit to 6 digit number. Now I want to convert this set of values to time representing the HH:MM:SS format. I thought of converting first to varchar then to time but it didn't work out. Can anyone help me out with the problem?
You can use TIMEFROMPARTS
SELECT
TIMEFROMPARTS(
YourColumn / 10000,
YourColumn / 100 % 100,
YourColumn % 100
)
FROM YourTable;
This happens to be what run times look like in msdb..sysjobschedules, which I've addressed here. Assuming "val" is your integer, try:
select dateadd(s, val - ((val / 100) * 40) - ((val / 10000) * 2400), 0/*or some date*/)
(subtracting out 40 seconds per minute and 40*100 + 2400 seconds per hour to get the actual number of seconds, then adding that many seconds to a date.)
Try:
date (dateadd(second,value,'19700101'))
I created a TIME table. This table has two columns: one for minutes and another one for seconds. I made their datatype as a Decimal.
Is there a way to create a derivative column where minutes and seconds are in this format mm:ss from my two columns?
IF NOT, How do I insert data into my minute column if its not a DECIMAL type? What type should it be?
Thank you!
Note I am using SQL server
Your comments make it sound like you're trying to do arithmetic on intervals (or durations).
SQL Server's time data type "Defines a time of a day. The time is without time zone awareness and is based on a 24-hour clock." You can't add two time values; 2 o'clock + 3 o'clock is literally nonsense. In SQL Server 2012 . . .
select cast('2:00' as time) + cast('3:00' as time)
Operand data type time is invalid for add operator.
Other dbms might return a nonsensical number.
Standard SQL includes a data type called interval, which supports the arithmetic and formatting you'd expect. So 2 o'clock + 3 hours would return 5:00:00 (5 o'clock). In the absence of support for the interval data type, store the most granular unit (seconds, for you) as an integer, and format it yourself for display. I might use a view, myself.
declare #val as integer;
-- 10:01:12, 10 hours, 1 minute, 12 seconds, in seconds.
set #val = (10 * 60 * 60) + (1 * 60) + 12;
-- Leading zeroes for minutes and seconds.
select #val as total_sec,
concat(#val / (60 * 60), ':', format((#val / 60) % 60, 'D2'), ':', format(#val % 60, 'D2')) as total_time
total_sec total_time
--
36072 10:01:12
As #mclaassen pointed out, I'd be curious why you aren't using the built in time data type.
That said, if you really want to build a time table by hand, then you can have a calculated column. Let's call it timeString.
alter table [time]
add timeString as (left('0' + cast([minutes] as varchar(10)), 2) + ':' + left('0' + cast([seconds] as varchar(10)), 2))
See https://msdn.microsoft.com/en-us/library/ms188300.aspx for documentation on calculated columns in SQL Server.
i'm trying to write a regular expression that will convert the hours into minutes.
Currently I have a value which give me the number of hours before the dot and the number of minutes after the dot, for example 6.10 is 6 hours and 10 minute.
Can i use a regular expression to look for the value before the dot and multiply by 60 (to get minutes) and then add the value after the dot (which is already in minutes)?
So as per the example used before, it would do:
(6 * 60) + 10
Thank you!
There's a STRTOK function to tokenize a string and then it's just:
select '12.34' as x,
cast(strtok(x,'.',1) as int) * 60 + cast(strtok(x,'.',2) as int)
If your value "6.10" is stored as a string, convert it to a number first:
SET #Input = CAST(#InputString AS FLOAT)
Then, use Modulus and Floor.
Total Minutes = The fractional part * 100 + the whole number part * 60.
So if your value 6.10 is contained in a variable named #Input, then you can get the value you wish with
SET #Output = (#Input % 1) * 100 + FLOOR(#Input, 0) * 60
If it's in a table then something more like this would be appropriate:
SELECT (Input % 1) * 100 + FLOOR(Input, 0) * 60 Output
FROM Table
The above only works if minutes are zero padded, e.g. 6 hours five minutes = 6.05. If you instead represent minutes without padding (6 hours five minutes = 6.5) then use the method that under suggests.
Regular expressions is probably an overkill for such a simple string manipulation. All you need is INDEX function to get the location of the dot and SUBSTR function to get hours and minutes.
Dot position:
select INDEX([yourstring], '.')
Hours (before the dot):
select SUBSTR([yourstring], 1, INDEX([yourstring], '.') - 1)
Minutes (after the dot):
select SUBSTR([yourstring], INDEX([yourstring], '.') + 1)
I Have Minutes as 1064 in a column called 'Efforts_in_minutes' and I need the Output in the format of HH:MM (i.e) 17:44. I have tried the below Query
SELECT Cast(Round(Total_Effort_in_Minutes / 60, 0, 2) AS VARCHAR)
+ ':'
+ Cast(Total_Effort_in_Minutes % 60 AS VARCHAR(2))
FROM PPS
I got the output as 17.000000:44 but What i Need is 17:44
Please advice how to achieve that.
The use of the Round function is unnecessary. Just do integer division:
select CAST(CAST(Total_Effort_in_Minutes AS INT) / 60 AS VARCHAR)
+ ':' + CAST(Total_Effort_in_Minutes % 60 AS VARCHAR(2) )
If your column Total_Effort_in_Minutes already has an integer data type, then you can simplify to:
select CAST(Total_Effort_in_Minutes / 60 AS VARCHAR)
+ ':' + CAST(Total_Effort_in_Minutes % 60 AS VARCHAR(2) )
If you need the minute part to be left-padded with zero to get at least 2 digits, then:
select RIGHT('0' + CAST(CAST(Total_Effort_in_Minutes AS INT) / 60 AS VARCHAR), 2)
+ ':' + CAST(Total_Effort_in_Minutes % 60 AS VARCHAR(2) )
SELECT DATEADD(MI,Total_Effort_in_Minutes,TIMEFROMPARTS(0,0,0,0,0))
FROM PPS
Best practice: The client should decide how to represent the time based on the locale, to allow for variants such as 24H clock vs AM/PM.
Please see this link: https://stackoverflow.com/a/19887500/6298495
Creating an inline function is a good solution provided in the link.
Just for fun:
SELECT CONVERT(CHAR(5), DATEADD(mi, 1064, 0), 8)
On Teradata SQL I am trying to convert the duration 30 hours and 30 minutes given as '3030' to 1) 30:30 and 2) 30.5 . Or, in another example 3 hours and 15 minutes as 1) 3:10 and 3) 3.25
I can use mod and other arithmetic operations. However, is there a default way of doing this in Teradata SQL?
Every interval has a FORMAT
select format(interval '3:30' hour to minute)
returns
-h(1):mm
but I never found a way to change it :-(
Assuming that you input is a string:
cast(col as int) / 100 + to_number(col) mod 100 / 60 -- numeric result
trim(cast(col as int format 'Z(8)9:99')) -- string result
You can just insert the character:
select substr(val, 1, 2) || ':' substr(val, 3, 2)
Or, convert the values to integers:
select cast(substr(val, 1, 2) as decimal(10, 2)) + cast(substr(val, 3, 2) as decimal(10, 2))/60.0
EDIT:
If you want to convert them to a number, you can do:
select (cast(hhmm as int) / 100 + (cast(hhmm as int) mod 100) / 60.0
This will return a number.