I have an column declared as int (called HourMil) which stores the time in military format. I need to convert this values to an formatted string (HH:MM)
example
HourMil = 710 -> must be 07:10
HourMil = 1305 -> must be 13:05
Actually I am using this code (and works ok) for convert the column HourMil to the string representation.
SELECT SUBSTRING(LEFT('0',4-LEN(CAST(HourMil AS VARCHAR)))+CAST(HourMil AS VARCHAR),1,2)+':'+SUBSTRING(LEFT('0',4-LEN(CAST(HourMil AS VARCHAR)))+CAST(HourMil AS VARCHAR),3,2) FROM MYTABLE
but I think this code can be improved.
By creating a date, then formatting it:
SELECT SUBSTRING(CONVERT(nvarchar, DATEADD
(hh, HourMil / 100, DATEADD(mi, HourMil % 100, '1900-01-01')), 8), 0, 6)
Equations:
H = HourMil / 100;
M = HourMil - ( HourMil / 100 ) * 100;
Examples of working:
H = 710 / 100 = 7
M = 710 - (710 / 100) * 100 = 10
H = 1305 / 100 = 13
M = 1305 - (1305 / 100) * 100 = 5
Note: All /* operators MUST working under decimal numbers only. (integers)
Then you SQL will be:
CONCAT(CAST(H AS VARCHAR(8)), ':', CAST(M AS VARCHAR(8)));
With equations final seems to be:
CONCAT(CAST((HourMil / 100) AS VARCHAR(8)), ':', CAST((HourMil - ( HourMil / 100 ) * 100) AS VARCHAR(8)));
This is another method and also a shortest one
select stuff(right('0'+ltrim(hourmail),4),3,0,':') from
(
select 710 as hourmail union all
select 1305
) as t
Related
I have this column Break in integer format.
The values are:
100 = 1h
130 = 1h and 30 minutes
I need to extract the minutes from this column:
100 = 1h = 60 minutes
130 = 1h and 30m = 90 minutes
I tried with this SQL, but it doesn't work:
select
convert(int, datediff(minute, 0, convert(varchar(8), dateadd(minute, TSH1."Break", ''), 114) ))
from TSH1
Can anyone help me?
Thanks
The following code will produce the output you want
select
(((CAST(TSH1."Break" AS INT) / 100) * 60) + (CAST(TSH1."Break" AS INT) % 100)) As col
from TSH1
I have a script which rounds a time length to the nearest 15 minutes. So for example 00:23:00 minutes to 00:37:59 duration will return 0.5 (decimal 30 minutes) etc continuous around the clock. I am trying to now get the script to work in half minutes so I need to shift this by 30 second offset for the rounding, so 00:22:29 seconds will go to 0.25 and 00:22:30 will round to 0.5. Here is the original script. So this needs to return 0.5 not 0.25. If you change the #finish to 08:22:29 it needs to then return 0.25. Thank you
declare #start datetime = '2020-03-01 08:00:00:000'
declare #finish datetime = '2020-03-01 08:22:30:000'
select
(CAST(DATEPART(hh, (DATEADD( minute, ( DATEDIFF( minute, 0, DATEADD( second, ( 15 * 60 ) / 2, (convert(varchar(5),(#finish - #start),108)) ) ) / 15 ) * 15, 0 ))) AS float) +
CAST(DATEPART(mi, (DATEADD( minute, ( DATEDIFF( minute, 0, DATEADD( second, ( 15 * 60 ) / 2, (convert(varchar(5),(#finish - #start),108)) ) ) / 15 ) * 15, 0 ))) AS float) / 60 +
CAST(DATEPART(ss, (DATEADD( minute, ( DATEDIFF( minute, 0, DATEADD( second, ( 15 * 60 ) / 2, (convert(varchar(5),(#finish - #start),108)) ) ) / 15 ) * 15, 0 ))) AS float) / 3600)
Here's another possible solution, using CASE to classify the modulo seconds over an hour:
SELECT DATEDIFF(second,#start,#finish) / 3600 +
CASE WHEN DATEDIFF(second,#start,#finish) % 3600 < 450 THEN 0.0
WHEN DATEDIFF(second,#start,#finish) % 3600 < 1350 THEN 0.25
WHEN DATEDIFF(second,#start,#finish) % 3600 < 2250 THEN 0.5
WHEN DATEDIFF(second,#start,#finish) % 3600 < 3150 THEN 0.75
ELSE 1
END
Solution is to add a dateadd(second, 30, #finish) I believe. Not the start time, this will then either push the result to over 00:23 if 00:22:30 and above or keep the length below 00:23. This should do the trick
In your solution, the problem is starting from the division of two integer numbers that would result to an integer. You can check for a solution.
Since you are dealing with time, it might be appropriate to use the CEILING function. If you think that this way is more appropriate, you could use:
declare #start datetime = '2020-03-01 08:00:00:000'
declare #finish datetime = '2020-03-01 08:22:30:000'
SELECT CEILING( DATEDIFF( ss, #start, #finish)/ (60*60.00) * 4) / 4
I have a postgres database that I can access with PGAdmin III. I run a script to change a number stored in a text field and then add left zeros to file it to four characters. It's a time field that must be stored as text. I'd like to do it in a single run instead of two. Here's the first clause to add hours to the time field as text;
UPDATE timetable
SET eta = (
CASE
WHEN (trips.starttime::int / 100) + (destination.zuluoffset * -1 ) < 24 THEN ((trips.starttime::int / 100) + (destination.zuluoffset * -1 )) * 100
WHEN (trips.starttime::int / 100) + (destination.zuluoffset * -1 ) > 23 THEN ((trips.starttime::int / 100) + (destination.zuluoffset * -1 ) - 24) * 100
END )
FROM
destination,
trips
WHERE
timetable.tripsid = trips.id;
This does fine and adds the desired number of hours while correcting for results of greater than 24 hours. However, this leave any times less than 1000 hours as three digits or even a single 0 for midnight. The field needs to be 4 characters.
So I run this as a second clause;
UPDATE timetable
SET eta = lpad(eta, 4, '0');
and this works also. But how can I add the lpad to the first Update clause? I tried putting the entire CASE statement in the lpad statement in place of eta like this;
SET eta = lpad((CASE statement here), 4, '0')
but I get this error;
ERROR: function lpad(numeric, integer, unknown) does not exist
LINE 3: SET eta = lpad((
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
I've tried casting eta with ::int, ::text, and ::varchar, but that just return a sytax error.
should be LPAD(your_col::text, 4, '0')
UPDATE timetable
SET eta = LPAD ((
CASE
WHEN (trips.starttime::int / 100) + (destination.zuluoffset * -1 ) < 24 THEN ((trips.starttime::int / 100) + (destination.zuluoffset * -1 )) * 100
WHEN (trips.starttime::int / 100) + (destination.zuluoffset * -1 ) > 23 THEN ((trips.starttime::int / 100) + (destination.zuluoffset * -1 ) - 24) * 100
END )::text, 4,'0')
FROM destination
INNER JOIN trips ON timetable.tripsid = trips.id;
Why are you using LPAD if the result of your CASE statement is numeric , use simply to_char :
UPDATE timetable
SET eta = to_char (
CASE
WHEN (trips.starttime::int / 100) + (destination.zuluoffset * -1 ) < 24 THEN ((trips.starttime::int / 100) + (destination.zuluoffset * -1 )) * 100
WHEN (trips.starttime::int / 100) + (destination.zuluoffset * -1 ) > 23 THEN ((trips.starttime::int / 100) + (destination.zuluoffset * -1 ) - 24) * 100
END , 'FM0000')
FROM destination
INNER JOIN trips ON timetable.tripsid = trips.id;
I need convert a millisecond value, 85605304.3587 to a value like 0d 18h 21m.
No idea on how to start that, is there something similar to a TimeSpan in SQL like there is in C#?
You can do the calculation explicitly. I think it is:
select floor(msvalue / (1000 * 60 * 60 * 24)) as days,
floor(msvalue / (1000 * 60 * 60)) % 24 as hours,
floor(msvalue / (1000 * 60)) % 60 as minutes
Note: Some databases use mod instead of %.
In MS SQL SERVER you can use next code:
with cte as (
select cast(85605304.3587 as int) / 1000 / 60 as [min]
), cte2 as (
select
cast([min] % 60 as varchar(max)) as minutes,
cast(([min] / 60) % 24 as varchar(max)) as hours,
cast([min] / (60 * 24) as varchar(max)) as days
from cte
)
select concat(days, 'd ', hours, 'h ', minutes, 'm') as tm
from cte2
Using native date & time functions, maybe:
SELECT
AsDateTime = DATEADD(MILLISECOND, 85605304, 0)
, AsDateTime2 = DATEADD(NANOSECOND, 7 * 100, DATEADD(MICROSECOND, 358, DATEADD(MILLISECOND, 85605304, CONVERT(datetime2, CONVERT(datetime, 0)))))
-- Incorrect datetime2 approach I initially did, has some precision loss, probably due to datetime's millisecond issue with 0's, 3's, and 7.'s
--SELECT DontDoThis = DATEADD(NANOSECOND, 7 * 100, DATEADD(MICROSECOND, 358, CONVERT(datetime2, DATEADD(MILLISECOND, 85605304, 0))))
datetime covers only 3 digits beyond seconds, while datetime2 will maintain 7 digits. Perhaps other ways that give date-like objects exist, I wouldn't know.
How to convert decimal to HH.MM format in SQl Server. Example:- 06.85 will be converted to 07.25, 06.60 will be converted to 7.00
SELECT
CASE
WHEN DecimalValue - FLOOR(DecimalValue) >= 0.6 THEN DecimalValue + 1 - 0.6
ELSE DecimalValue
END AS HHMMFormat
FROM
MyTable
Obviously the + 1 - 0.6 could be replaced by + 0.4 but I thought that + 1 - 0.6 more clearly showed the reason for the addition.
select floor(06.85) + cast(((06.85 - floor(06.85))*100) as int) / 60 + cast((cast((06.85 - floor(06.85)) * 100 as int) % 60) as float) / 100
select floor(06.60) + cast(((06.60 - floor(06.60))*100) as int) / 60 + cast((cast((06.60 - floor(06.60)) * 100 as int) % 60) as float) / 100