SQL AVERAGE TIME - sql

I have the following query in MSSQL:
select
TRANSACTION_TYPE_ID
,COUNT(TRANSACTION_TYPE_ID)AS NUMBER_OF_TRANSACTIONS
,CAST(SUM(AMOUNT)AS DECIMAL (30,2)) AS TOTAL
FROM
[ONLINE_TRANSACTION]
WHERE CONVERT(CHAR(8), CREATED_ON, 114) >='17:30' AND AMOUNT IS NOT NULL AND
TRANSACTION_TYPE_ID !='CHEQUE-STOP-TRANS-TYPE'
GROUP BY TRANSACTION_TYPE_ID
ORDER BY TRANSACTION_TYPE_ID
I want to show the type of transactions TRANSATION_TYPE_ID as above the total amount of each type of transaction as above BUT also the average time these transactions occurred CREATED_ON which is datetime I still have not find a good way of doing this?

Based on Randolph Potter's answer, you can find the average time like:
avg(DATEPART(hh,created_on)*60 + DATEPART(mi,created_on)) % 24 as AvgHour,
avg(DATEPART(hh,created_on)*60 + DATEPART(mi,created_on)) / 24 as AvgMinute

One way would be to convert the time to seconds, calculate the average, and then convert it back to hours, minutes and seconds for the result.

If your talking about the time of day and not looking to get a specific date, ie. 5:32 instead of Jan 4, 2012 5:32, the below could help. Sorry about the caps, it's the way I'm used to writing SQL.
CONVERT(VARCHAR,AVG(DATEPART(HH,CREATED_ON)*60 + DATEPART(MI,CREATED_ON)) / 60) + ':' +
CASE WHEN CONVERT(VARCHAR,AVG(DATEPART(HH,CREATED_ON)*60 + DATEPART(MI,CREATED_ON)) % 60) < 10
THEN '0'+CONVERT(VARCHAR,AVG(DATEPART(HH,CREATED_ON)*60 + DATEPART(MI,CREATED_ON)) % 60)
ELSE CONVERT(VARCHAR,AVG(DATEPART(HH,CREATED_ON)*60 + DATEPART(MI,CREATED_ON)) % 60)
END AS AVG_CREATED_ON

SELECT FROM_UNIXTIME( ( ROUND((UNIX_TIMESTAMP( floor(timestamp_column)) / 60 ),0) * 60 ) ) rounded_time
FROM mysql_table
WHERE timestamp_column BETWEEN STR_TO_DATE('31/07/2012','%d/%m/%Y')
AND STR_TO_DATE('01/08/2012','%d/%m/%Y')

Related

How to extract the hour of day from an epoch and count each instance that occurs during that hour?

I have a question that I feel is pretty straight forward but is giving me some issues.
I have a column in table X called event_time which is an epoch. I am wanting to extract the hour of day out of that and count the number of rides that have occurred during that hour.
So the output will end up being a bar chart with x values 0-24 and the Y being the number of instances that occur (which is bike rides for example).
Here is what I have now, that isn't giving me the correct output:
select extract(hour from to_timestamp(start_time)::date) as hr,
count(*) as ct
from x
group by hr
order by hr asc
Any hints or help are appreciated.
Thanks
You can use arithmetic:
select floor( (start_time % (24 * 60 * 60)) / (60 * 60) ) as hour,
count(*)
from x
group by hour;
Or convert to a date/time and extract the hour:
select extract(hour from '1970-01-01'::date + start_time * interval '1 second') as hour, count(*)
from x
group by hour;

duration between two columns with format hhmmss

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!!

Convert time in the form mm:ss into seconds in Postgres

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

How to sum time datatype in sql server

I have query which gives sum of total talk time for an Agent all the years
SELECT
CONVERT(TIME, DATEADD(s, SUM(( DATEPART(hh, TalkTime) * 3600 ) + ( DATEPART(mi, TalkTime) * 60 ) + DATEPART(ss, TalkTime)), 0))
FROM [CRMIntegration].[dbo].[Five9CallLog]
where AGENT_NAME = 'XYZ'
which is giving me '00:37:01.0000000'
but when i sum up total talk time for this year till now using the below query
SELECT
CONVERT(TIME, DATEADD(s, SUM(( DATEPART(hh, TalkTime) * 3600 ) + ( DATEPART(mi, TalkTime) * 60 ) + DATEPART(ss, TalkTime)), 0))
FROM [CRMIntegration].[dbo].[Five9CallLog]
where AGENT_NAME = 'XYZ'
and DateOfcall between
DATEADD(yy, DATEDIFF(yy,0,getdate()), 0) and dateadd(day,datediff(day,1,GETDATE()),0)
result of the query is '23:34:38.0000000',but this should be always less than or equal to the first result
Is the function i am using for calculating total talk time is correct?
I suspect your first result is greater than 1 day, but that is being truncated by using TIME. Instead of adding seconds to 0 and converting to TIME, you could use DATEDIFF() to get total minutes:
SELECT DATEDIFF(MINUTE,0,TalkTime)
Ideally you'd have a start/end time to use instead of 0, because you'll run into an overflow if you need to get too precise and try starting from 0. If it's always relative to the start of the day, you can use:
SELECT DATEDIFF(SECOND,CAST(TalkTime AS DATE),TalkTime)
Likewise, you could simply remove the TIME conversion from what you already have.

Calculate Average Time Over 24 hour period

I'm working in Teradata and am trying to calulate the average time a job completes.
Data Values:
Job Name Start Date End Date End Time
D_BDW_CCIP_SRM_LD 10/10/2012 10/11/2012 01:41:49
D_BDW_CCIP_SRM_LD 10/9/2012 10/10/2012 00:19:56
D_BDW_CCIP_SRM_LD 10/8/2012 10/8/2012 23:37:18
D_BDW_CCIP_SRM_LD 10/5/2012 10/5/2012 23:39:47
D_BDW_CCIP_SRM_LD 10/4/2012 10/4/2012 23:42:47
D_BDW_CCIP_SRM_LD 10/3/2012 10/3/2012 23:41:54
The average is coming back with 16:07 instead of 00:07. What I need to happen is that the calculations where the job finishes next day understands that the time expanded.
In Excel I could do this by adding one day to the end time and then averaging and displaying as a time.
How do I do this in Teradata?
This is such an interesting question! UPDATED with correct syntax: Assuming your START_DATE and END_DATE are DATE values and END_TIME is a TIME value, here is a solution:
select cast( avg( case
when start_date <> end_date
then extract(second from end_time)
+ extract(minute from end_time) * 60
+ extract(hour from end_time) * 3600
+ 86400
else extract(second from end_time)
+ extract(minute from end_time) * 60
+ extract(hour from end_time) * 3600
end) mod 86400) as decimal(10,4))
* INTERVAL '00:00:01.00' HOUR TO SECOND as avg_time
from your_table
The CASE expression "adds" one day (86,400 seconds) as you suggested when using Excel to determine the average seconds since midnight into an intermediate result and converted into a TIME column.
To be fair, I received help from the Teradata Forum formatting the result, but I like this so much I'll be using it myself.
This seems to do the trick, but I'd be interested in seeing if there is another way.
SELECT job_name,
case when avg_end_time_in_minutes > 60*24 then avg_end_time_in_minutes - 60*24
else avg_end_time_in_minutes end as avg_adjusted,
case when max_end_time_in_minutes > 60*24 then max_end_time_in_minutes - 60*24
else max_end_time_in_minutes end as max_adjusted,
CAST((CAST(avg_adjusted / 60 AS INTEGER) (FORMAT '9(2)')) AS CHAR(2))||':'||
CAST((CAST((avg_adjusted / 60 MOD 1)*60 AS INTEGER) (FORMAT '9(2)')) AS CHAR(2))
avg_adjusted_time,
CAST((CAST(max_adjusted / 60 AS INTEGER) (FORMAT '9(2)')) AS CHAR(2))||':'||
CAST((CAST((max_adjusted / 60 MOD 1)*60 AS INTEGER) (FORMAT '9(2)')) AS CHAR(2))
max_adjusted_time
FROM (
SELECT job_name,
AVG(end_time_in_minutes) avg_end_time_in_minutes,
MAX(CAST(end_time_in_minutes AS DECIMAL(8,2))) max_end_time_in_minutes
FROM (
SELECT job_name,
CAST(substr(end_time, 1, 2) AS INTEGER)*60
+ CAST(substr(end_time, 4, 2) AS INTEGER)
+ cast(end_date - start_date as integer)*60*24 AS end_time_in_minutes
FROM dabank_prod_ops_tb.bdw_tables_load_tracker_view a
WHERE a.status = 'COMPLETED'
AND a.start_date BETWEEN CURRENT_DATE - 31 AND CURRENT_DATE -1
AND a.end_time IS NOT NULL
) a
GROUP BY 1
) b
First, figure out the number of seconds that the end time is from midnight on the start date. We can then use that to calculate the average number of seconds taken, and then add that to midnight to find the average end time.
select
avg(extract(second from end_time) + 60 *
(extract(minute from end_time) + 60 *
(extract(hour from end_time) + 24 *
(end_date - start_date))) as avg_duration_in_seconds
cast(avg_duration_in_seconds / 60 / 60 as integer) as avg_hours
mod(cast(avg_duration_in_seconds / 60 as integer), 60) as avg_minutes
mod(cast(avg_duration_in_seconds as integer), 60) as avg_seconds,
cast('00:00:00' as time) +
cast(avg_hours as interval hour) +
cast(avg_minutes as interval minute) +
cast(avg_seconds as interval second) as avg_end_time
from my_table
Be aware though that if the average ends up over 24 hours, avg_end_time will be something like 00:01:15 rather than 24:01:15.