Using Postgres 9.3.5
My table has duration data in the as a text field stored as minutes:seconds,
i.e 4:52
I want the value as total seconds (i.e 4 x 60) + 52 = 292
But table also contains values such as
3:34:21 (3 hours, 34 minutes and 21 seconds)
21 (21 seconds)
How can I write SQL to correct calculate duration in seconds for all these cases.
Update
select (case when duration like '%:%:%'
then extract(epoch from duration::time)
else extract(epoch from ('00:' || duration) ::time)
end
)as seconds
from discogs.track t1
;
So I have this but unfortunately some values are not quite valid causing it to fail
00:70:01
How do I either ignore such values or convert them (i.e 70 x 60 + 1)
http://sqlfiddle.com/#!17/9eecb/19379
I expand %:% text to %:%:% texts and then simply split on delimiter ';'. So I am getting integer values which can be used in calculations.
SELECT
orig_duration,
hours_in_seconds + minutes_in_seconds + seconds as seconds
FROM (
SELECT
orig_duration,
(split_part(duration, ':', 1))::int * 60 * 60 as hours_in_seconds,
(split_part(duration, ':', 2))::int * 60 as minutes_in_seconds,
(split_part(duration, ':', 3))::int as seconds
FROM (
SELECT
duration as orig_duration,
case when duration like '%:%:%' then duration else '00:' || duration end as duration
FROM (
SELECT unnest(ARRAY['70:01','3:34:21','4:52']::text[]) as duration
)s
)s
)s
Result:
orig_duration seconds
------------- -------
70:01 4201
3:34:21 12861
4:52 292
You can convert the value to time and extract the time component. You do need to take the variable format into account:
select (case when t like '%:%:%'
then extract(epoch from t::time)
else extract(epoch from ('00:' || t) ::time)
end) as seconds
You added a new format. You can do:
select (case when t like '%:%:%'
then extract(epoch from t::time)
when t like '%:%'
then extract(epoch from ('00:' || t) ::time)
else t::int
end) as seconds
Related
I'm trying to convert milliseconds to format HH:MM:SS or MM:SS, but I keep getting the same error.
Here's the error:
java.sql.SQLException: [Simba][AthenaJDBC](100071) An error has been thrown from the AWS Athena client. SYNTAX_ERROR: line 5:19: Unexpected parameters (time, varchar(5)) for function date_format. Expected: date_format(timestamp with time zone, varchar(x)) , date_format(timestamp, varchar(x)) [Execution ID: 89bfd858-9992-439f-ad84-b59bfd1cbde8]
Here's my code:
SELECT
column_a,
round(AVG((milliseconds) / 1000)) AS Seconds,
(case when milliseconds/1000 < 60 * 60
then time '00:00:00' + milliseconds * interval '1' second, '%i:%s'
else time '00:00:00' + milliseconds * interval '1' second, '%H:%i:%s'
end) as hhmmss,
round((AVG((column_b)) / 1099511627776),2) AS b,
COUNT(column_c) AS c
FROM
table
GROUP BY
column_a
Tried with this one as well
(case when milliseconds/1000 < 60 * 60
then date_format(time '00:00:00' + milliseconds * interval '1' second, '%i:%s')
else date_format(time '00:00:00' + milliseconds * interval '1' second, '%H:%i:%s')
end) as hhmmss
Any help, please?
You can just cast your time to timestamp:
select date_format(cast(time '00:00:00' + 23 * interval '1' second as timestamp), '%H:%i:%s')
Output:
_col0
00:00:23
Note that this will work only if you have less than 24 hours interval in your milliseconds, otherwise you will need to do math yourself and concat results into desired string.
P.S. Should not milliseconds * interval '1' second be (milliseconds/1000) * interval '1' second?
How can I determine the difference / duration between two columns, which have the following format:
HHMMSS.
Leading zeros are swallowed by the system (Oracle DB).
0 o'clock is a "0".
3 o'clock is "300".
23:50 clock is "235000".
Whatever, 24:00 is also reported as "240000".
That means I have the column "Start" and the column "End".
How can you determine the duration using SQL?
Convert the values to seconds using arithmetic:
select hhmmss, floor(hhmmss / 10000) * 60 * 60 + (mod(hhmmss, 10000) / 100) * 60 + mod(hhmmss, 100)
from (select 235000 as hhmmss from dual) x
Then subtract the seconds. That will give you the duration in seconds.
With your column names, this would look like:
select ( (floor(end / 10000) * 60 * 60 + (mod(end, 10000) / 100) * 60 + mod(end, 100)) -
(floor(start / 10000) * 60 * 60 + (mod(start, 10000) / 100) * 60 + mod(start, 100))
) as diff_seconds
To convert this back to a string, you can use to_char():
select to_char(date '2000-01-01' + diff_seconds * interval '1' second, 'HH24:MI:SS')
You can achieve the duration in hour/minutes/seconds using to_date as following:
Select round(
(to_date(lpad(end,6,'0'),'HHMISS')
- to_date(lpad(start,6,'0'),'HHMISS') ) * 24
, 2) diff_in_hours
-- multiply it by another 60 to get diff in minutes (24*60)
-- multiply it by another 3600 to get diff in seconds (24*3600)
from your_table
To get the output in HHMISS just add it to sysdate
Select
TO_CHAR(Trunc(sysdate) + (to_date(lpad(end,6,'0'),'HHMISS')
- to_date(lpad(start,6,'0'),'HHMISS')) , 'HH:MI:SS') as diff_HHMISS
from your_table
Cheers!!
I would like to convert in PL/SQL miliseconds to Time(hh:mm:ss)
21649000 to 06:00:49
or
83293000 to 23:08:13
Use NUMTODSINTERVAL with SECOND option :
select NUMTODSINTERVAL( 83293000 / 1000, 'SECOND' ) "Time" from dual t;
Time
-------------------
+000000000 23:08:13
This is a quite self-explanatory way:
select val,
floor( val / 1000 / 60 / 60 ) as hours,
floor( mod(val / 1000 / 60 , 60) ) as minutes,
floor( mod(val / 1000 , 60) ) as seconds
from (
select 21649000 val from dual union
select 83293000 val from dual
)
VAL HOURS MINUTES SECONDS
---------- ---------- ---------- ----------
21649000 6 0 49
83293000 23 8 13
This does not handle days, so the number of milliseconds must be less than 24 hours.
This gives numbers, you can edit it the way you need to get your desired output format/type.
If you only want second precision you could divide the number by 1000 to get seconds, and by 86400 to get a fraction of a day, then add that to midnight on any nominal date - and convert the result to a string:
select to_char(date '1970-01-01' + (21649000/86400000), 'HH24:MI:SS') as time
from dual;
TIME
--------
06:00:49
select to_char(date '1970-01-01' + (83293000/86400000), 'HH24:MI:SS') as time
from dual;
TIME
--------
23:08:13
This only works properly for values less than a day, i.e. where your original number is less than 86400000; higher than that and you only see the leftover in the second day.
The below query worked for me to convert to the Milliseconds to the HH:MM:SS
SELECT
TO_CHAR(TRUNC([ColumnName]/3600000),'FM9900') || ':' ||
TO_CHAR(TRUNC(MOD([ColumnName],3600000)/60000),'FM00') || ':' ||
TO_CHAR( trunc(MOD([ColumnName],60000)/1000),'FM00') FROM [TableName]`
From my view, I am getting a column with value like '0 0:0:0.343009' which shows the difference between two timestamps, to millisecond precision.
I would like to show them as a string like 343 milliseconds or other value but should be a millisecond conversion.
I had similar post in the past but that time column was a DATE datatype, and this time it is a TIMESTAMP. I am using the FLOOR function to change the output to a numeric value to show a more user friendly result.
I used sample query to find a difference of dates. Here created_time is a TIMESTAMP datatype:
select msg_guid,
(max(case when payload_type = 1 then created_time end) -
(case when max(case when payload_type = 2 then created_time end) <>
trunc(max(case when payload_type = 2 then created_time end))
then max(case when payload_type = 2 then created_time end)
when max(case when payload_type = 3 then created_time end) <>
trunc(max(case when payload_type = 3 then created_time end))
then max(case when payload_type = 3 then created_time end)
end)
) as diff
from table t
group by msg_guid;
When you add or subtract timestamps, the result is an interval, not another timestamp. You can use the extract function to pull the components out of that. If you value is always going to be sub-second you can just extract the seconds, and multiply by a thousand to get the milliseconds:
with t as (
select 1 as msg_guid,
interval '0 0:0:0.343009' day to second as diff
from dual
)
select trunc(extract (second from diff) * 1000)
from t;
TRUNC(EXTRACT(SECONDFROMDIFF)*1000)
-----------------------------------
343
Here your real query would take the place of the dummy CTE I used with an interval literal.
If the interval might be more than a second then you would presumably want to get the entire value in milliseconds, so you'd need to extract all the elements and add them together, multiplying each based on what they represent - so a full day would be 86400000 milliseconds etc.; the plain elements would come out like:
column diff format a25
with t as (
select 1 as msg_guid,
systimestamp - trunc(systimestamp) as diff
from dual
)
select diff,
extract (day from diff) as dd,
extract (hour from diff) as hh,
extract (minute from diff) as mi,
extract (second from diff) as ss
from t;
DIFF DD HH MI SS
---------------------- ---------- ---------- ---------- ----------
0 9:13:26.150627 0 9 13 26.150627
And you'd combine them like:
with t as (
select 1 as msg_guid,
systimestamp - trunc(systimestamp) as diff
from dual
)
select diff,
trunc(1000 * (
extract (day from diff) * (60*60*24)
+ extract (hour from diff) * (60*60)
+ extract (minute from diff) * 60
+ extract (second from diff)
)) as milliseconds
from t;
DIFF MILLISECONDS
---------------------- ------------
0 9:13:27.650365 33207650
But based on your previous question, maybe you want it as a string, as the separate components:
with t as (
select 1 as msg_guid,
systimestamp - trunc(systimestamp) as diff
from dual
)
select diff,
extract (day from diff) || ' DAYS '
|| extract (hour from diff) || ' HOURS '
|| extract (minute from diff) || ' MINUTES '
|| trunc(extract (second from diff)) || ' SECONDS '
|| (trunc(extract (second from diff) * 1000)
- (trunc(extract (second from diff)) * 1000)) || ' MILLISECONDS'
as text
from t;
DIFF TEXT
---------------------- -------------------------------------------------------
0 9:43:38.896007 0 DAYS 9 HOURS 43 MINUTES 38 SECONDS 896 MILLISECONDS
SQL Fiddle based on your sample data, sort of, and with the time calculation reversed so the value is positive.
I have a table with over 100,000 rows that contain the following columns: ID, Time, and Boolean.
The time column tracks time down to the second.
I need a query that will find all instances of Boolean = 1 for every 5 minute interval of time from the start of the table to the end, then group the count by time interval.
The table represents 4 hours of data, so I should get 48 rows of results.
I'm using MS SQL Server.
I've tried a few approaches, but the time interval logic is giving me a hard time.
EDIT: I figured it out!
SELECT DATEADD(MINUTE, DATEDIFF(MINUTE, 0, timestamp)/5 * 5,0), COUNT(*)
FROM table
WHERE isrepeat = 1
GROUP BY by DATEADD(MINUTE, DATEDIFF(MINUTE, 0, timestamp)/5 * 5,0)
ORDER BY by 1
This should do. You can group by your results by an interval of time/5.
select
cast(to_char(Time, 'mi') as int) / 5 * 5 || ' - ' || cast(to_char(Time, 'mi') as int) / 5 * 5 + 5 as "Interval",
count(1)
from tableName
where
Boolean = 1
group by
cast(to_char(Time, 'mi') as int) / 5
select * from tableName where Time
BETWEEN DATEADD(minute, -5, current_timestamp)
AND current_timestamp