Call Report Calculations with Multiple SQL Queries
Data Connector exposes your Cloud Voice call database so you can build dashboards in business-intelligence tools such as Grafana and Power BI. The report templates supplied for those platforms are each limited to a single query per report, which covers most cases. A few reports, though, are assembled from several result sets that must be combined after the queries run. This page is the reference for those reports: for each one it lists the SQL to execute and the calculations to apply to the returned rows so you can reproduce the report in your own BI tooling.
A few conventions used throughout:
- Queries read from
cdr.cdr_cleaned(cleaned Call Detail Records, or CDRs) orqueue_log(queue events).pbx.ai_usage_recordholds transcription usage. - Acronyms you will meet below: CDR (Call Detail Record, one row per call leg), QCB (Queue Callback, where a caller keeps their place in line and is called back instead of waiting on hold), and SLA (Service Level Agreement, here the share of calls answered within the target wait time).
- The date ranges and the extension, queue, and trunk identifiers shown below are examples. Substitute the values for your own report.
Extension Call Statistics report
Section titled “Extension Call Statistics report”This report reflects each extension’s total activity, so you retrieve outbound and inbound statistics separately and then merge the two result sets by extension number.
-
Retrieve outbound call statistics per extension.
SELECTsrc as ext_num,SUM(failed) AS failed,SUM(vm) AS vm,SUM(CASE WHEN c.scenario = 'mobile' THEN 0 WHEN COALESCE(mobile.mobile_answered, 0) = 1 THEN 1 WHEN c.call_flow = '' THEN c.answered WHEN c.call_flow != ''AND c.is_group = 1 THEN c.answered WHEN c.call_flow = 'Monitor' THEN c.answered ELSE 0 END) AS answered,SUM(CASE WHEN c.scenario = 'mobile' THEN 0 WHEN COALESCE(mobile.mobile_answered, 0) = 1 THEN 0 WHEN c.call_flow = '' THEN c.no_answer WHEN c.call_flow != ''AND c.is_group = 1 THEN c.no_answer WHEN c.call_flow = 'Monitor' THEN c.no_answer ELSE 0 END) AS total_no_answered,SUM(CASE WHEN c.scenario = 'mobile' THEN 0 WHEN COALESCE(mobile.mobile_answered, 0) = 1 THEN 0 WHEN c.call_flow = '' THEN c.busy WHEN c.call_flow != ''AND c.is_group = 1 THEN c.busy WHEN c.call_flow = 'Monitor' THEN c.busy ELSE 0 END) AS busy,SUM(CASE WHEN c.scenario = 'mobile' THEN 0 WHEN COALESCE(mobile.mobile_answered, 0) = 1 THEN 0 WHEN c.call_flow = '' THEN c.abandoned WHEN c.call_flow != ''AND c.is_group = 1 THEN c.abandoned WHEN c.call_flow = 'Monitor' THEN c.abandoned ELSE 0 END) AS abandoned,SUM(CASE WHEN c.scenario = 'mobile' THEN 0 WHEN COALESCE(mobile.mobile_answered, 0) = 1 THEN COALESCE(mobile.mobile_ring, 0) WHEN c.call_flow = '' THEN c.ring_duration WHEN c.call_flow != ''AND c.is_group = 1 THEN c.ring_duration WHEN c.call_flow = 'Monitor' THEN c.ring_duration ELSE 0 END) AS ring_duration,SUM(CASE WHEN c.scenario = 'mobile' THEN 0 WHEN COALESCE(mobile.mobile_answered, 0) = 1 THEN COALESCE(mobile.mobile_talk, 0) WHEN c.call_flow = '' THEN (c.talk_duration + c.hold_duration) WHEN c.call_flow != ''AND c.is_group = 1 THEN (c.talk_duration + c.hold_duration) WHEN c.call_flow = 'Monitor' THEN (c.talk_duration + c.hold_duration) ELSE 0 END) AS talk_durationFROMcdr.cdr_cleaned AS cLEFT JOIN (SELECTm.uid,MAX(m.answered) AS mobile_answered,MAX(CASE WHEN m.answered = 1 THEN m.ring_duration ELSE 0 END) AS mobile_ring,MAX(CASE WHEN m.answered = 1 THEN m.talk_duration + m.hold_duration ELSE 0 END) AS mobile_talkFROMcdr.cdr_cleaned AS mWHEREm.scenario = 'mobile'GROUP BY`m`.`uid`) AS mobile ON c.uid = mobile.uidWHEREc.src in ('1028', '1016', '1003', '1004', '1006','1014', '1033', '1000', '1034', '1023','1027', '1021', '1019', '1022', '1020','1015', '1018', '1025', '1011', '1012','1029', '1024', '1032', '1008', '1007','1010', '1013', '1026', '1030', '1017','1001', '1009', '1031', '1002', '1005')AND c.start_ts >= 1773590400000000AND c.start_ts <= 1776268799999999GROUP BY`src`The query returns:
ext_num: Extension number.answered: Calls the extension answered.total_no_answered: Calls the extension did not answer.busy: Calls that arrived while the extension was busy.abandoned: Calls the caller dropped before reaching the extension.vm: Calls routed to the extension’s voicemail.failed: Outbound calls the extension was unable to complete.ring_duration: Total time from call start to answer.talk_duration: Total time from answer to call end.
-
Retrieve inbound call statistics per extension.
SELECTdst as ext_num,SUM(failed) AS failed,SUM(vm) AS vm,SUM(CASE WHEN c.scenario = 'mobile' THEN 0 WHEN COALESCE(mobile.mobile_answered, 0) = 1 THEN 1 WHEN c.call_flow = '' THEN c.answered WHEN c.call_flow != ''AND c.is_group = 0 THEN c.answered ELSE 0 END) AS answered,SUM(CASE WHEN c.scenario = 'mobile' THEN 0 WHEN COALESCE(mobile.mobile_answered, 0) = 1 THEN 0 WHEN c.call_flow = '' THEN (c.no_answer) WHEN c.call_flow != ''AND c.is_group = 0AND c.is_display = 1 THEN (c.no_answer) ELSE 0 END) AS total_no_answered,SUM(CASE WHEN c.scenario = 'mobile' THEN 0 WHEN COALESCE(mobile.mobile_answered, 0) = 1 THEN 0 WHEN c.call_flow = '' THEN c.busy WHEN c.call_flow != ''AND c.is_group = 0AND c.is_display = 1 THEN c.busy ELSE 0 END) AS busy,SUM(CASE WHEN c.scenario = 'mobile' THEN 0 WHEN COALESCE(mobile.mobile_answered, 0) = 1 THEN 0 WHEN c.call_flow = '' THEN c.abandoned ELSE 0 END) AS abandoned,SUM(CASE WHEN c.scenario = 'mobile' THEN 0 WHEN COALESCE(mobile.mobile_answered, 0) = 1 THEN COALESCE(mobile.mobile_ring, 0) WHEN c.call_flow = '' THEN c.ring_duration WHEN c.call_flow != ''AND c.is_group = 0AND c.is_display = 1 THEN c.ring_duration ELSE 0 END) AS ring_duration,SUM(CASE WHEN c.scenario = 'mobile' THEN 0 WHEN COALESCE(mobile.mobile_answered, 0) = 1 THEN COALESCE(mobile.mobile_talk, 0) WHEN c.call_flow = '' THEN (c.talk_duration + c.hold_duration) WHEN c.call_flow != ''AND c.is_group = 0 THEN (c.talk_duration + c.hold_duration) ELSE 0 END) AS talk_durationFROMcdr.cdr_cleaned AS cLEFT JOIN (SELECTm.uid,MAX(m.answered) AS mobile_answered,MAX(CASE WHEN m.answered = 1 THEN m.ring_duration ELSE 0 END) AS mobile_ring,MAX(CASE WHEN m.answered = 1 THEN m.talk_duration + m.hold_duration ELSE 0 END) AS mobile_talkFROMcdr.cdr_cleaned AS mWHEREm.scenario = 'mobile'GROUP BY`m`.`uid`) AS mobile ON c.uid = mobile.uidWHEREc.dst in ('1028', '1016', '1003', '1004', '1006','1014', '1033', '1000', '1034', '1023','1027', '1021', '1019', '1022', '1020','1015', '1018', '1025', '1011', '1012','1029', '1024', '1032', '1008', '1007','1010', '1013', '1026', '1030', '1017','1001', '1009', '1031', '1002', '1005')AND c.start_ts >= 1773590400000000AND c.start_ts <= 1776268799999999GROUP BY`dst`The query returns the same set of columns as the outbound query (
ext_num,answered,total_no_answered,busy,abandoned,vm,failed,ring_duration,talk_duration), calculated for inbound calls. -
Merge the outbound and inbound result sets on
ext_numto produce the complete per-extension statistics.
Extension Call Activity report
Section titled “Extension Call Activity report”This report breaks each extension’s activity down by time period. As with the statistics report, you retrieve outbound and inbound figures separately and merge them, here by both extension number and time period.
-
Retrieve outbound call statistics per extension.
SELECTsrc as ext_num,MONTH(datetime) AS time,SUM(failed) AS failed,SUM(vm) AS vm,SUM(CASE WHEN c.scenario = 'mobile' THEN 0 WHEN COALESCE(mobile.mobile_answered, 0) = 1 THEN 1 WHEN c.call_flow = '' THEN c.answered WHEN c.call_flow != ''AND c.is_group = 1 THEN c.answered WHEN c.call_flow = 'Monitor' THEN c.answered ELSE 0 END) AS answered,SUM(CASE WHEN c.scenario = 'mobile' THEN 0 WHEN COALESCE(mobile.mobile_answered, 0) = 1 THEN 0 WHEN c.call_flow = '' THEN c.no_answer WHEN c.call_flow != ''AND c.is_group = 1 THEN c.no_answer WHEN c.call_flow = 'Monitor' THEN c.no_answer ELSE 0 END) AS total_no_answered,SUM(CASE WHEN c.scenario = 'mobile' THEN 0 WHEN COALESCE(mobile.mobile_answered, 0) = 1 THEN 0 WHEN c.call_flow = '' THEN c.busy WHEN c.call_flow != ''AND c.is_group = 1 THEN c.busy WHEN c.call_flow = 'Monitor' THEN c.busy ELSE 0 END) AS busy,SUM(CASE WHEN c.scenario = 'mobile' THEN 0 WHEN COALESCE(mobile.mobile_answered, 0) = 1 THEN 0 WHEN c.call_flow = '' THEN c.abandoned WHEN c.call_flow != ''AND c.is_group = 1 THEN c.abandoned WHEN c.call_flow = 'Monitor' THEN c.abandoned ELSE 0 END) AS abandoned,SUM(CASE WHEN c.scenario = 'mobile' THEN 0 WHEN COALESCE(mobile.mobile_answered, 0) = 1 THEN COALESCE(mobile.mobile_ring, 0) WHEN c.call_flow = '' THEN c.ring_duration WHEN c.call_flow != ''AND c.is_group = 1 THEN c.ring_duration WHEN c.call_flow = 'Monitor' THEN c.ring_duration ELSE 0 END) AS ring_duration,SUM(CASE WHEN c.scenario = 'mobile' THEN 0 WHEN COALESCE(mobile.mobile_answered, 0) = 1 THEN COALESCE(mobile.mobile_talk, 0) WHEN c.call_flow = '' THEN (c.talk_duration + c.hold_duration) WHEN c.call_flow != ''AND c.is_group = 1 THEN (c.talk_duration + c.hold_duration) WHEN c.call_flow = 'Monitor' THEN (c.talk_duration + c.hold_duration) ELSE 0 END) AS talk_durationFROMcdr.cdr_cleaned AS cLEFT JOIN (SELECTm.uid,MAX(m.answered) AS mobile_answered,MAX(CASE WHEN m.answered = 1 THEN m.ring_duration ELSE 0 END) AS mobile_ring,MAX(CASE WHEN m.answered = 1 THEN m.talk_duration + m.hold_duration ELSE 0 END) AS mobile_talkFROMcdr.cdr_cleaned AS mWHEREm.scenario = 'mobile'GROUP BY`m`.`uid`) AS mobile ON c.uid = mobile.uidWHEREc.src in ('1032', '1008', '1007', '1010', '1013','1026', '1030', '1017', '1001', '1009','1031', '1002', '1005', '1028', '1016','1003', '1004', '1006', '1014', '1033','1000', '1034', '1023', '1027', '1021','1019', '1022', '1020', '1015', '1018','1025', '1011', '1012', '1029', '1024')AND c.start_ts >= 1767196800000000AND c.start_ts <= 1798732799999999GROUP BYsrc,timeORDER BYtime,ext_num ascThe query returns
time(the period),ext_num, and the same activity columns as the Extension Call Statistics report:answered,total_no_answered,busy,abandoned,failed,vm,ring_duration, andtalk_duration. -
Retrieve inbound call statistics per extension.
SELECTdst as ext_num,MONTH(datetime) AS time,SUM(failed) AS failed,SUM(vm) AS vm,SUM(CASE WHEN c.scenario = 'mobile' THEN 0 WHEN COALESCE(mobile.mobile_answered, 0) = 1 THEN 1 WHEN c.call_flow = '' THEN c.answered WHEN c.call_flow != ''AND c.is_group = 0 THEN c.answered ELSE 0 END) AS answered,SUM(CASE WHEN c.scenario = 'mobile' THEN 0 WHEN COALESCE(mobile.mobile_answered, 0) = 1 THEN 0 WHEN c.call_flow = '' THEN (c.no_answer) WHEN c.call_flow != ''AND c.is_group = 0AND c.is_display = 1 THEN (c.no_answer) ELSE 0 END) AS total_no_answered,SUM(CASE WHEN c.scenario = 'mobile' THEN 0 WHEN COALESCE(mobile.mobile_answered, 0) = 1 THEN 0 WHEN c.call_flow = '' THEN c.busy WHEN c.call_flow != ''AND c.is_group = 0AND c.is_display = 1 THEN c.busy ELSE 0 END) AS busy,SUM(CASE WHEN c.scenario = 'mobile' THEN 0 WHEN COALESCE(mobile.mobile_answered, 0) = 1 THEN 0 WHEN c.call_flow = '' THEN c.abandoned ELSE 0 END) AS abandoned,SUM(CASE WHEN c.scenario = 'mobile' THEN 0 WHEN COALESCE(mobile.mobile_answered, 0) = 1 THEN COALESCE(mobile.mobile_ring, 0) WHEN c.call_flow = '' THEN c.ring_duration WHEN c.call_flow != ''AND c.is_group = 0AND c.is_display = 1 THEN c.ring_duration ELSE 0 END) AS ring_duration,SUM(CASE WHEN c.scenario = 'mobile' THEN 0 WHEN COALESCE(mobile.mobile_answered, 0) = 1 THEN COALESCE(mobile.mobile_talk, 0) WHEN c.call_flow = '' THEN (c.talk_duration + c.hold_duration) WHEN c.call_flow != ''AND c.is_group = 0 THEN (c.talk_duration + c.hold_duration) ELSE 0 END) AS talk_durationFROMcdr.cdr_cleaned AS cLEFT JOIN (SELECTm.uid,MAX(m.answered) AS mobile_answered,MAX(CASE WHEN m.answered = 1 THEN m.ring_duration ELSE 0 END) AS mobile_ring,MAX(CASE WHEN m.answered = 1 THEN m.talk_duration + m.hold_duration ELSE 0 END) AS mobile_talkFROMcdr.cdr_cleaned AS mWHEREm.scenario = 'mobile'GROUP BY`m`.`uid`) AS mobile ON c.uid = mobile.uidWHEREc.dst in ('1032', '1008', '1007', '1010', '1013','1026', '1030', '1017', '1001', '1009','1031', '1002', '1005', '1028', '1016','1003', '1004', '1006', '1014', '1033','1000', '1034', '1023', '1027', '1021','1019', '1022', '1020', '1015', '1018','1025', '1011', '1012', '1029', '1024')AND c.start_ts >= 1767196800000000AND c.start_ts <= 1798732799999999GROUP BYdst,timeORDER BYtime,ext_num ascThe query returns the same columns as the outbound query, calculated for inbound calls.
-
Merge the outbound and inbound result sets by extension number and time period to produce the complete report.
Agent Call Summary report
Section titled “Agent Call Summary report”This report summarizes each agent’s queue activity and average call times. Retrieve inbound and outbound queue statistics separately, merge them per agent, then derive the averages.
-
Retrieve inbound queue call statistics per agent.
SELECTc.dst AS agent,count(answered) AS answered_call,SUM(CASE WHEN sub.duration != NULL THEN c.duration + sub.duration ELSE c.duration END) AS duration,SUM(talk_duration) AS talking_time,SUM(hold_duration) AS hold_time,SUM(CASE WHEN sub.ring_duration != NULL THEN c.ring_duration + sub.ring_duration ELSE c.ring_duration END) AS waiting_timeFROMcdr.cdr_cleaned as cLEFT JOIN (SELECTuid,dst,sum(duration) as duration,sum(ring_duration) AS ring_durationFROMcdr.cdr_cleaned as cWHEREstart_ts >= 1773590400000000AND start_ts <= 1776268799999999AND (c.dst IN ('1000', '1001'))AND src != 'PBX'AND call_flow_number = '6404'AND call_flow = 'Queue'AND disposition != 'ANSWERED'AND is_group = '0'GROUP BYuid,dst) AS sub ON c.uid = sub.uidand c.dst = sub.dstWHEREstart_ts >= 1773590400000000AND start_ts <= 1776268799999999AND (c.dst IN ('1000', '1001'))AND src != 'PBX'AND call_flow_number = '6404'AND call_flow = 'Queue'AND disposition = 'ANSWERED'AND is_group = '0'GROUP BY`c`.`dst`The query returns:
agent: Agent number.answered_call: Inbound queue calls the agent answered.duration: Time the agent spent handling inbound queue calls, from ring to hang-up.talking_time: Time the agent spent talking on inbound calls.hold_time: Time the agent held inbound calls.waiting_time: Time inbound queue calls waited before the agent answered.
-
Retrieve outbound queue call statistics per agent.
SELECTsrc AS agent,COUNT(uid) AS total_call,SUM(answered) AS answered_call,SUM(CASE WHEN disposition = 'ANSWERED' THEN duration ELSE 0 END) AS duration,SUM(CASE WHEN disposition = 'ANSWERED' THEN talk_duration ELSE 0 END) AS talking_time,SUM(CASE WHEN disposition = 'ANSWERED' THEN hold_duration ELSE 0 END) AS hold_time,SUM(CASE WHEN disposition = 'ANSWERED' THEN ring_duration ELSE 0 END) AS waiting_timeFROM`cdr`.`cdr_cleaned`WHEREstart_ts >= 1773590400000000AND start_ts <= 1776268799999999AND call_type = 'Outbound'AND src in ('1000', '1001')AND NOT(srcname = 'Conference Call')AND is_group = '0'GROUP BY`src`The query returns:
agent: Agent number.total_call: Outbound calls the agent placed.answered_call: Outbound calls the agent answered.duration: Time the agent spent handling outbound queue calls, from ring to hang-up.talking_time: Time the agent spent talking on outbound calls.hold_time: Time the agent held outbound calls.waiting_time: Time outbound queue calls waited before being answered.
-
Merge the inbound and outbound statistics by agent extension number to build the combined totals:
total_duration: Sum ofdurationfrom the inbound and outbound queue calls.total_talk_time: Sum oftalking_timeandhold_timefrom the inbound and outbound queue calls.total_hold_time: Sum ofhold_timefrom the inbound and outbound queue calls.total_waiting_time: Sum ofwaiting_timefrom the inbound and outbound queue calls.total_call: Sum of the inboundanswered_calland the outboundtotal_call.inbound_answered_call: Sum ofanswered_callfrom the inbound queue calls.inbound_duration: Sum oftalking_timeandhold_timefrom the inbound queue calls.outbound_total_call: Sum oftotal_callfrom the outbound queue calls.outbound_answered_call: Sum ofanswered_callfrom the outbound queue calls.outbound_duration: Sum oftalking_timeandhold_timefrom the outbound queue calls.
-
Calculate each agent’s average durations:
avg_server_time=total_duration/ (inbound_answered_call+outbound_answered_call)avg_talking_time=total_talk_time/ (inbound_answered_call+outbound_answered_call)avg_hold_time=total_hold_time/ (inbound_answered_call+outbound_answered_call)avg_waiting_time=total_waiting_time/ (inbound_answered_call+outbound_answered_call)
Agent Login Activity report
Section titled “Agent Login Activity report”This report shows when agents logged in to and out of a queue. Retrieve the login and logout events from the queue log.
SELECT agent, timestamp, eventFROM `queue_log`WHERE ( queuename = 'queue-6402' and event in('ADDMEMBER', 'REMOVEMEMBER') ) AND (timestamp >= 1773590400) AND (timestamp <= 1776268799)GROUP BY agent, timestamp, eventORDER BY timestamp ascThe query returns:
agent: Agent number.timestamp: When the agent logged in to or out of the queue.event:ADDMEMBER: The agent logged in to the queue.REMOVEMEMBER: The agent logged out of the queue.
Agent Pause Activity report
Section titled “Agent Pause Activity report”This report shows when agents paused and resumed service. Retrieve the pause and unpause events from the queue log.
SELECT agent, timestamp, event, data1FROM `queue_log`WHERE ( queuename = 'queue-6404' and event in( 'PAUSE', 'UNPAUSE', 'REMOVEMEMBER' ) ) AND (timestamp >= 1774022400) AND (timestamp <= 1776700799)GROUP BY agent, timestamp, event, data1ORDER BY timestamp ascThe query returns:
agent: Agent number.timestamp: When the agent paused or resumed service.data1: Pause reason.event:PAUSE: The agent paused service.UNPAUSE: The agent resumed service.
Agent Performance report
Section titled “Agent Performance report”This report aggregates queue call records from several datasets, then merges them into final per-agent metrics.
-
Aggregate queue performance data, excluding
q_half_consultrecords.SELECT`dst`,Count(*) as total_calls,sum(answered) as answered_calls,sum(missed) as missed_calls,sum(abandoned) as abandoned_calls,max(ring_duration) as max_ring_time,sum(answered_ring_duration) as total_answered_ring_time,sum(ring_duration) as total_ring_time,sum(hold_duration) as total_hold_time,sum(talk_duration) as total_talking_time,sum(member_hold_duration) as total_member_hold_duration,sum(member_answered_count) as total_member_answeredFROMcdr.cdr_cleaned as cWHEREc.is_group = 1AND (not (c.ring_duration <= 1and c.abandoned = 1))AND flag != 'q_half_consult'AND c.start_ts >= 1776614400000000AND c.start_ts <= 1776700799999999AND call_flow = 'Queue'AND call_flow_number = '6404'GROUP BY`dst`The query returns:
dst: Queue number.total_calls: Calls the queue received.answered_calls: Calls the queue answered.missed_calls: Calls the queue missed.abandoned_calls: Calls the caller abandoned.max_ring_time: Longest time a caller waited in the queue before reaching an agent.total_answered_ring_time: Time from call start to answer.total_ring_time: Time from call start to answer.total_hold_time: Time the call was held.total_talking_time: Time from answer to hang-up.total_member_hold_duration: Time agents held calls.total_member_answered: Calls agents answered.
-
Aggregate the queue performance records that carry the
q_half_consultflag.SELECTc.dst,sum(c.ring_duration) as total_ring_time,sum(CASE WHEN h.answered > 0 THEN c.ring_duration ELSE 0 END) as total_answered_ring_time,max(c.ring_duration + h.ring_duration) as max_ring_timeFROMcdr.cdr_cleaned as cLEFT JOIN (SELECTuid,answered,ring_durationFROMcdr.cdr_cleaned as cWHEREc.is_group = 1AND flag != 'q_half_consult'AND c.start_ts >= 1776614400000000AND c.start_ts <= 1776700799999999AND call_flow = 'Queue'AND call_flow_number = '6404') AS h ON h.uid = c.another_uidWHEREc.is_group = 1AND flag = 'q_half_consult'AND c.start_ts >= 1776614400000000AND c.start_ts <= 1776700799999999AND call_flow = 'Queue'AND call_flow_number = '6404'GROUP BY`c`.`dst`The query returns:
dst: Queue number.total_ring_time: Time from call start to answer.total_answered_ring_time: Time from call start to answer, for answered calls.max_ring_time: Longest time a caller waited in the queue before reaching an agent.
-
Merge the two datasets into queue-level totals:
total_answered_ring_time= sum oftotal_answered_ring_timefrom both datasetstotal_ring_time= sum oftotal_ring_timefrom both datasetsmax_ring_time= maximummax_ring_timeacross both datasets
-
Calculate the queue-level metrics from the aggregated data:
average_waiting_time=total_answered_ring_time/answered_callsaverage_talking_time= (total_talking_time+total_hold_time) /answered_callsaverage_handle_time= (total_answered_ring_time+total_talking_time+total_hold_time) /answered_callsaverage_hold_time=total_hold_time/answered_callsanswered_rate=answered_calls/total_callsmissed_rate=missed_calls/total_callsabandoned_rate=abandoned_calls/total_callsall_call_average_waiting_time=total_ring_time/total_calls
-
Aggregate agent-level records, excluding callback-related calls and invalid abandoned records.
SELECTc.uid,c.call_flow_number as queue,c.dst as agent,sum(c.answered) as answered_calls,sum(c.missed) as missed_calls,max(c.ring_duration) as max_ring_time,sum(c.answered_ring_duration) as total_answered_ring_time,sum(c.ring_duration) as total_ring_time,sum(c.talk_duration) as total_talking_time,sum(c.hold_duration) as total_hold_timeFROMcdr.cdr_cleaned as cLEFT JOIN cdr.cdr_cleaned AS h ON h.uid = c.uidAND h.is_group = 1AND h.ring_duration <= 1AND h.disposition = 'ABANDONED'WHEREc.call_flow IN ('Queue', 'QCB')AND c.call_flow_number = '6404'AND c.dst IN ('1000', '1001')AND c.is_group != 1AND c.disposition != 'ABANDONED'AND c.src != 'PBX'AND h.uid IS NULLAND c.start_ts >= 1776614400000000AND c.start_ts <= 1776700799999999GROUP BYc.call_flow_number,c.uid,c.dstThe query returns:
uid: The CDR’s unique ID.queue: Queue number.agent: Agent number.answered_calls: Calls the agent answered.missed_calls: Calls the agent missed.max_ring_time: Longest ring time before a call reached the agent.total_answered_ring_time: Time from call start to answer, for answered calls.total_ring_time: Time from call start to answer.total_talking_time: Time from answer to hang-up.total_hold_time: Time the agent held calls.
-
Aggregate the agent-level records that relate to callback calls.
SELECTc.uid,c.call_flow_number as queue,c.dst as agent,sum(c.answered) as answered_calls,sum(c.missed) as missed_calls,max(c.ring_duration) as max_ring_time,sum(c.answered_ring_duration) as total_answered_ring_time,sum(c.ring_duration) as total_ring_time,sum(c.talk_duration) as total_talking_time,sum(c.hold_duration) as total_hold_timeFROMcdr.cdr_cleaned as cLEFT JOIN cdr.cdr_cleaned AS h ON h.uid = c.uidAND h.is_group = 1AND h.ring_duration <= 1AND h.disposition = 'ABANDONED'WHEREc.call_flow IN ('Queue', 'QCB')AND c.call_flow_number = '6404'AND c.dst IN ('1000', '1001')AND c.is_group != 1AND c.disposition != 'ABANDONED'AND c.src = 'PBX'AND h.uid IS NULLAND c.start_ts >= 1776614400000000AND c.start_ts <= 1776700799999999GROUP BYc.call_flow_number,c.uid,c.dstThe query returns the same columns as the previous step.
-
Retrieve agent-level callback (QCB) statistics.
SELECTcall_flow_number as queue,src as agent,count(*) as total_calls,sum(answered) as answered_calls,sum(missed) as missed_calls,max(ring_duration) as max_ring_time,sum(answered_ring_duration) as total_answered_ring_time,sum(ring_duration) as total_ring_time,sum(duration) as total_talking_time,sum(hold_duration) as total_hold_timeFROM`cdr`.`cdr_cleaned`WHEREcall_flow_number = '6404'AND is_qcb = 1AND src IN ('1000', '1001')AND start_ts >= 1776614400000000AND start_ts <= 1776700799999999AND call_flow = ('Queue')GROUP BYcall_flow_number,srcThe query returns
queue,agent,total_calls,answered_calls,missed_calls,max_ring_time,total_answered_ring_time,total_ring_time,total_talking_time, andtotal_hold_timefor the callback calls. -
Add the callback talking time into the agent statistics.
agent_talk_time_map[queue_agent] = total_talking_time -
Aggregate the statistics at queue and agent level.
agentMap[queue_agent].dst = agentagentMap[queue_agent].total_calls += answered_calls + missed_callsagentMap[queue_agent].answered_calls += answered_callsagentMap[queue_agent].missed_calls += missed_callsagentMap[queue_agent].total_ring_time += total_ring_timeagentMap[queue_agent].total_talking_time += agent_talk_time_map[queue_agent] // add only onceagent_answered_ring_duration[queue_uid_agent] = total_answered_ring_timeif answered_calls > 0 {agent_answered[queue_uid_agent] = 1} -
Calculate the agent-level metrics.
answered_ring_time = total_answered_ring_timeif answered_calls > 0 || agent_answered[queue_uid_agent] == 1 {answered_ring_time = total_ring_time}agentMap.total_calls += answered_calls + missed_callsagentMap.answered_calls += answered_callsagentMap.missed_calls += missed_callsagentMap.total_answered_ring_time += answered_ring_timeagentMap.total_ring_time += total_ring_timeagentMap.total_talking_time += total_talking_time + total_hold_timeagent_answered_ring_duration[queue_uid_agent] += answered_ring_timeagentMap.max_ring_time = max(agent_answered_ring_duration[queue_agent]...)agentMap.avg_talking_time = agentMap.total_talking_time / agentMap.answered_callsagentMap.avg_waiting_time = agentMap.total_answered_ring_time / agentMap.answered_callsagentMap.miss_rate = agentMap.missed_calls / agentMap.total_calls
Queue AVG Wait and Talk Time report
Section titled “Queue AVG Wait and Talk Time report”This report tracks average wait and talk times per period. Aggregate the queue call data and calculate the derived metrics.
-
Aggregate the queue call data, excluding
q_half_consultrecords, into thenormal_datadataset.SELECTDAY(datetime) AS time,Count(*) as total_calls,sum(answered) as answered_calls,sum(answered_ring_duration) as total_answered_ring_time,sum(ring_duration) as total_ring_time,sum(talk_duration + hold_duration) as total_talking_timeFROM`cdr`.`cdr_cleaned`WHEREis_group = 1AND flag != 'q_half_consult'AND start_ts >= 1774972800000000AND start_ts <= 1777564799999999AND call_flow = 'Queue'AND call_flow_number = '6404'GROUP BY`time`The query returns:
time: When the call was received.total_calls: Calls the queue received.answered_calls: Calls the queue answered.total_answered_ring_time: Time from call start to answer.total_ring_time: Time from call start to answer.total_talking_time: Time from answer to hang-up.
-
Aggregate the queue call data with the
q_half_consultrecords into theq_half_consult_datadataset.SELECTday AS time,sum(c.ring_duration) as total_ring_time,sum(CASE WHEN h.answered > 0 THEN c.ring_duration ELSE 0 END) as total_answered_ring_time,max(c.ring_duration + h.ring_duration) as max_ring_timeFROMcdr.cdr_cleaned as cLEFT JOIN (SELECTuid,answered,ring_durationFROMcdr.cdr_cleaned as cWHEREc.is_group = 1AND flag != 'q_half_consult'AND c.start_ts >= 1774972800000000AND c.start_ts <= 1777564799999999AND call_flow = 'Queue'AND call_flow_number = '6404') AS h ON h.uid = c.another_uidWHEREis_group = 1AND flag = 'q_half_consult'AND start_ts >= 1774972800000000AND start_ts <= 1777564799999999AND call_flow = 'Queue'AND call_flow_number = '6404'GROUP BY`time`The query returns:
time: When the call was received.total_ring_time: Time from call start to answer.total_answered_ring_time: Time from call start to answer.max_ring_time: Longest time a caller waited in the queue.
-
Merge
normal_dataandq_half_consult_datainto the final metrics.normal_data[time].timenormal_data[time].total_callsnormal_data[time].answered_callsnormal_data[time].total_talking_timenormal_data[time].total_answered_ring_time += q_half_consult_data[time].total_answered_ring_timenormal_data[time].total_ring_time += q_half_consult_data[time].total_ring_timenormal_data[time].average_waiting_time = normal_data[time].total_answered_ring_time / normal_data[time].answered_callsnormal_data[time].average_talking_time = normal_data[time].total_talking_time / normal_data[time].answered_callsnormal_data[time].all_call_average_waiting_time = normal_data[time].total_ring_time / normal_data[time].total_calls
Queue Callback Summary report
Section titled “Queue Callback Summary report”This report summarizes queue callbacks. Aggregate the queue call records by the callback-related fields.
SELECT dst, COUNT(*) AS total_count, SUM(CASE WHEN is_qcb = 1 THEN 1 ELSE 0 END) AS qcb_count, SUM( CASE WHEN is_qcb = 1 AND qcb_status = 'success' THEN 1 ELSE 0 END ) AS qcb_success_count, SUM( CASE WHEN is_qcb = 1 AND qcb_status != 'success' THEN 1 ELSE 0 END ) AS qcb_failed_countFROM `cdr`.`cdr_cleaned`WHERE start_ts >= 1774108800000000 AND start_ts <= 1776787199999999 AND call_flow_number in ('6404') AND call_flow = 'Queue' AND is_group = '1'GROUP BY `dst`The query returns:
dst: Queue number.qcb_failed_count: Failed callbacks.qcb_success_count: Successful callbacks.qcb_count: Callbacks that callers requested successfully.total_count: Calls the queue received.
Queue Performance report
Section titled “Queue Performance report”This report aggregates queue call data and derives the performance metrics.
-
Aggregate the queue call data, excluding
q_half_consultrecords, into thenormal_datadataset.SELECT`dst`,Count(*) as total_calls,sum(answered) as answered_calls,sum(missed) as missed_calls,sum(abandoned) as abandoned_calls,max(ring_duration) as max_ring_time,sum(answered_ring_duration) as total_answered_ring_time,sum(ring_duration) as total_ring_time,sum(hold_duration) as total_hold_time,sum(talk_duration) as total_talking_time,sum(member_hold_duration) as total_member_hold_duration,sum(member_answered_count) as total_member_answered,SUM(CASE WHEN dst = '6404'AND disposition = 'ANSWERED'AND (ring_duration - COALESCE(join_announcement_duration, 0)) < 60 THEN 1 ELSE 0 END) AS total_sla_callFROMcdr.cdr_cleaned as cWHEREc.is_group = 1AND (not (c.ring_duration <= 1and c.abandoned = 1))AND (not (c.talk_duration < 1and c.answered = 1))AND flag != 'q_half_consult'AND c.start_ts >= 1774108800000000AND c.start_ts <= 1776787199999999AND call_flow = 'Queue'AND call_flow_number = '6404'GROUP BY`dst` -
Aggregate the queue call data with the
q_half_consultrecords into theq_half_consult_datadataset.SELECTc.dst,sum(c.abandoned) as abandoned_calls,sum(c.ring_duration) as total_ring_time,sum(CASE WHEN h.answered > 0 THEN c.ring_duration ELSE 0 END) as total_answered_ring_time,max(c.ring_duration + h.ring_duration) as max_ring_timeFROMcdr.cdr_cleaned as cLEFT JOIN (SELECTuid,answered,ring_durationFROMcdr.cdr_cleaned as cWHEREc.is_group = 1AND flag != 'q_half_consult'AND c.start_ts >= 1774108800000000AND c.start_ts <= 1776787199999999AND call_flow = 'Queue'AND call_flow_number = '6404') AS h ON h.uid = c.another_uidWHEREc.is_group = 1AND flag = 'q_half_consult'AND c.start_ts >= 1774108800000000AND c.start_ts <= 1776787199999999AND call_flow = 'Queue'AND call_flow_number = '6404'GROUP BY`c`.`dst` -
Merge
normal_dataandq_half_consult_datainto the final metrics.normal_data[dst].queue_num = normal_data[dst].dstnormal_data[dst].total_calls = normal_data[dst].total_callsnormal_data[dst].answered_calls = normal_data[dst].answered_callsnormal_data[dst].abandoned_calls = normal_data[dst].abandoned_callsnormal_data[dst].missed_calls = normal_data[dst].missed_callsnormal_data[dst].total_sla_call = normal_data[dst].total_sla_callnormal_data[dst].total_answered_ring_time += q_half_consult_data[dst].total_answered_ring_timenormal_data[dst].total_ring_time += q_half_consult_data[dst].total_ring_timeif q_half_consult_data[dst].max_ring_time > normal_data[dst].max_ring_time {normal_data[dst].max_waiting_time = q_half_consult_data[dst].max_ring_time}normal_data[dst].average_waiting_time = normal_data[dst].total_answered_ring_time / normal_data[dst].answered_callsnormal_data[dst].average_talking_time = (normal_data[dst].total_talking_time + normal_data[dst].total_hold_time) / normal_data[dst].answered_callsnormal_data[dst].average_handle_time = (normal_data[dst].total_answered_ring_time + normal_data[dst].total_talking_time + normal_data[dst].total_hold_time) / normal_data[dst].answered_callsnormal_data[dst].average_hold_time = (normal_data[dst].total_hold_time) / normal_data[dst].answered_callsnormal_data[dst].answered_rate = normal_data[dst].answered_calls / normal_data[dst].total_callsnormal_data[dst].missed_rate = normal_data[dst].missed_calls / normal_data[dst].total_callsnormal_data[dst].abandoned_rate = normal_data[dst].abandoned_calls / normal_data[dst].total_callsnormal_data[dst].all_call_average_waiting_time = normal_data[dst].total_ring_time / normal_data[dst].total_calls
Queue Performance Activity report
Section titled “Queue Performance Activity report”This report aggregates queue call data across call scenarios and computes performance metrics per period.
-
Aggregate the queue call records, excluding
q_half_consultrecords, into the basenormal_datadataset.SELECTday AS time,Count(*) as total_calls,sum(answered) as answered_calls,sum(missed) as missed_calls,sum(abandoned) as abandoned_calls,max(ring_duration) as max_ring_time,sum(answered_ring_duration) as total_answered_ring_time,sum(ring_duration) as total_ring_time,sum(hold_duration) as total_hold_time,sum(talk_duration) as total_talking_time,sum(member_hold_duration) as total_member_hold_duration,sum(member_answered_count) as total_member_answered,SUM(CASE WHEN dst = '6404'AND disposition = 'ANSWERED'AND (ring_duration - COALESCE(join_announcement_duration, 0)) < 60 THEN 1 ELSE 0 END) AS total_sla_callFROM`cdr`.`cdr_cleaned`WHEREis_group = 1AND flag != 'q_half_consult'AND (not (ring_duration <= 1and abandoned = 1))AND start_ts >= 1774972800000000AND start_ts <= 1777564799999999AND call_flow = 'Queue'AND call_flow_number = '6404'GROUP BY`time` -
Aggregate the queue call records with the
q_half_consultflag into theq_half_consult_datadataset.SELECTday AS time,sum(c.abandoned) as abandoned_calls,sum(c.ring_duration) as total_ring_time,sum(CASE WHEN h.answered > 0 THEN c.ring_duration ELSE 0 END) as total_answered_ring_time,max(c.ring_duration + h.ring_duration) as max_ring_timeFROMcdr.cdr_cleaned as cLEFT JOIN (SELECTuid,answered,ring_durationFROMcdr.cdr_cleaned as cWHEREc.is_group = 1AND flag != 'q_half_consult'AND c.start_ts >= 1774972800000000AND c.start_ts <= 1777564799999999AND call_flow = 'Queue'AND call_flow_number = '6404') AS h ON h.uid = c.another_uidWHEREis_group = 1AND flag = 'q_half_consult'AND start_ts >= 1774972800000000AND start_ts <= 1777564799999999AND call_flow = 'Queue'AND call_flow_number = '6404'GROUP BY`time` -
Combine
normal_dataandq_half_consult_datainto the final queue performance metrics.normal_data[time].time = normal_data[dst].timenormal_data[time].total_calls = normal_data[time].total_callsnormal_data[time].answered_calls = normal_data[time].answered_callsnormal_data[time].abandoned_calls = normal_data[time].abandoned_callsnormal_data[time].missed_calls = normal_data[time].missed_callsnormal_data[time].total_sla_call = normal_data[time].total_sla_callnormal_data[time].total_answered_ring_time += q_half_consult_data[time].total_answered_ring_timenormal_data[time].total_ring_time += q_half_consult_data[time].total_ring_timeif q_half_consult_data[time].max_ring_time > normal_data[time].max_ring_time {normal_data[time].max_waiting_time = q_half_consult_data[time].max_ring_time}normal_data[time].answered_hold_time = normal_data[time].total_hold_timenormal_data[time].answered_call_time = normal_data[time].total_answered_ring_time + normal_data[time].total_talking_time + normal_data[time].total_hold_timenormal_data[time].total_talk_time = normal_data[time].total_talking_time + normal_data[time].total_hold_timenormal_data[time].answered_waiting_time = normal_data[time].total_answered_ring_timenormal_data[time].average_waiting_time = normal_data[time].total_answered_ring_time / normal_data[time].answered_callsnormal_data[time].average_talking_time = (normal_data[time].total_talking_time + normal_data[time].total_hold_time) / normal_data[time].answered_callsnormal_data[time].average_handle_time = (normal_data[time].total_answered_ring_time + normal_data[time].total_talking_time + normal_data[time].total_hold_time) / normal_data[time].answered_callsnormal_data[time].average_hold_time = (normal_data[time].total_hold_time) / normal_data[time].answered_callsnormal_data[time].total_waiting_time = normal_data[time].total_ring_timenormal_data[time].sla = normal_data[time].total_sla_call / normal_data[time].total_callsnormal_data[time].answered_rate = normal_data[time].answered_calls / normal_data[time].total_callsnormal_data[time].missed_rate = normal_data[time].missed_calls / normal_data[time].total_callsnormal_data[time].abandoned_rate = normal_data[time].abandoned_calls / normal_data[time].total_callsnormal_data[time].all_call_average_waiting_time = normal_data[time].total_ring_time / normal_data[time].total_calls
Unreturned Missed Call report
Section titled “Unreturned Missed Call report”This report identifies missed calls that have not been returned. Query the missed-call records, then correlate them with answered and callback records to decide whether each missed call was returned.
-
Retrieve the missed call records.
SELECTid,uid,timestamp,src,srcname,dst,dstname,ring_duration,dstnameprefix,disposition,call_flow,call_typeFROM`cdr`.`cdr_cleaned`WHEREcall_type = 'Inbound'AND is_display = 1AND disposition in ('ABANDONED', 'NO ANSWER', 'BUSY')AND (NOT(disposition = 'ABANDONED'and ring_duration < 5))AND start_ts >= 1774108800000000AND start_ts <= 1776787199999999ORDER BYuid,timestamp; -
Remove duplicate records that share a
uid, keeping only the record with the latesttimestampfor eachuid, and build the baselist_mapdataset.list_map[uid].uid = miss_call_data.uidlist_map[uid].timestamp = miss_call_data.timestamplist_map[uid].src = miss_call_data.srclist_map[uid].srcname = miss_call_data.srcnamelist_map[uid].dst = miss_call_data.dstlist_map[uid].dstname = miss_call_data.dstnamelist_map[uid].call_to_type = miss_call_data.call_flowlist_map[uid].unreturn_status = 0list_map[uid].return_time = 0list_map[uid].miss_call_type = miss_call_data.dispositionlist_map[uid].call_type = miss_call_data.call_typelist_map[uid].ring_duration = miss_call_data.ring_duration -
Retrieve the answered call records related to the caller number.
SELECTmax(timestamp) as timestamp,src,dst,dispositionFROM`cdr`.`cdr_cleaned`WHEREtimestamp > 1775534367893043AND is_display = 1AND disposition = 'ANSWERED'AND (src = '2233123456'or dst = '2233123456')GROUP BYsrc,dst,disposition -
Determine the latest answered-call timestamp for each caller number.
// has_return_time_mapif answered_call_data[src].timestamp > has_return_time_map[src] {has_return_time_map[src] = answered_call_data[src].timestamp} -
Retrieve the callback records associated with the missed caller number.
SELECTmax(timestamp) as timestamp,src,dst,dispositionFROM`cdr`.`cdr_cleaned`WHEREtimestamp >= 1775534367893043AND is_display = 1AND ((dst = '2233123456')or (src = '2233123456'and disposition = 'ANSWERED'))GROUP BYsrc,dst,disposition -
Determine the latest callback timestamp for each missed caller number.
// last_return_time_mapif last_answered_call_data[src].timestamp > last_return_time_map[src] {last_return_time_map[src] = last_answered_call_data[src].timestamp} -
Determine the unreturned status for each missed call record.
list_map[uid].unreturn_status = 2src = list_map[uid].srcif has_return_time_map[src] > list_map[uid].timestamp {list_map[uid].unreturn_status = 1}if last_return_time_map[src] > list_map[uid].timestamp {list_map[uid].return_time = last_return_time_map[src]}
Ring Group Statistics report
Section titled “Ring Group Statistics report”This report aggregates ring group activity at both the group level and the member level, then combines the two into the final structured result.
-
Aggregate call statistics at the ring group level to build the list dataset.
SELECTdst as ring_group_num,SUM(CASE WHEN disposition = 'ANSWERED' THEN 1 ELSE 0 END) AS answered_calls,count(*) as total_callsFROM`cdr`.`cdr_cleaned`WHEREis_group = 1AND start_ts >= 1776441600000000AND start_ts <= 1779119999999999AND call_flow = 'RingGroup'AND call_flow_number in ('6300', '6301', '6302')GROUP BY`dst` -
Aggregate call statistics at the member level to build the
member_listdataset.SELECT`dst`,call_flow_number as ring_group_num,SUM(CASE WHEN disposition = 'ANSWERED' THEN 1 ELSE 0 END) AS answered_calls,count(*) as total_callsFROM`cdr`.`cdr_cleaned`WHEREis_group = 0AND start_ts >= 1776441600000000AND start_ts <= 1779119999999999AND call_flow = 'RingGroup'AND call_flow_number in ('6300', '6301', '6302')GROUP BYdst,call_flow_number -
Sort the ring group list and the
member_listby answered rate in descending order, then generate the final structured output.{"ring_group_num":"6200","answered_calls":10,"total_calls":20,"member_list":[{"ext_num":"1000","answered_calls":10,"total_calls":20}...]}
PBX Call Activity report
Section titled “PBX Call Activity report”This report aggregates call activity from three sources, trunk calls, device calls, and internal calls. Each dataset is calculated separately, then used for the overall analysis.
-
Retrieve data for calls made or received over trunks.
a. Retrieve trunk call activity, excluding multi-party calls.
SELECTmax(day) AS time,max(srctrunk) as srctrunk,max(dsttrunk) as dsttrunk,SUM(talk_duration + hold_duration) as total_talk_duration,MAX(concurrent) as max_concurrent_call,uid,0 as total_callsFROM`cdr`.`cdr_cleaned`WHERE(srctrunk in ('Trunk A', 'Trunk B')or dsttrunk in ('Trunk A', 'Trunk B'))AND is_display = 1AND (NOT(dstnameprefix in ('Queue', 'RingGroup')and disposition = 'ANSWERED'))AND NOT(srcname = 'Conference Call')AND start_ts >= 1774972800000000AND start_ts <= 1777564799999999GROUP BY`uid`;b. Calculate the call volume, total talk duration, and maximum concurrent calls for the same trunk within the same period, excluding multi-party calls.
c. Retrieve trunk call activity, including multi-party calls.
SELECTmax(day) AS time,srctrunk,dsttrunk,SUM(talk_duration + hold_duration) as total_talk_duration,MAX(concurrent) as max_concurrent_call,uid,COUNT(*) as total_callsFROM`cdr`.`cdr_cleaned`WHERE(srctrunk in ('Trunk A', 'Trunk B')or dsttrunk in ('Trunk A', 'Trunk B'))AND is_display = 1AND (NOT(dstnameprefix in ('Queue', 'RingGroup')and disposition = 'ANSWERED'))AND srcname = 'Conference Call'AND start_ts >= 1774972800000000AND start_ts <= 1777564799999999GROUP BYsrctrunk,dsttrunk,uid;d. Calculate the call volume, total talk duration, and maximum concurrent calls for the same trunk within the same period, including multi-party calls.
-
Retrieve system-wide call activity, covering internal, inbound, and outbound calls across all trunks.
a. Retrieve device call activity, excluding audio conference and paging.
SELECTmax(day) AS time,uid,SUM(talk_duration + hold_duration) as total_talk_duration,MAX(concurrent) as max_concurrent_callFROM`cdr`.`cdr_cleaned`WHERE(NOT(dstnameprefix in ('Queue', 'RingGroup')and disposition = 'ANSWERED'))AND call_flow != 'Audio Conference'AND call_flow != 'Paging'AND dstnameprefix != 'Paging'AND start_ts >= 1774972800000000AND start_ts <= 1777564799999999GROUP BY`uid`;b. Calculate the call volume, total talk duration, and maximum concurrent calls within the same period, excluding multi-party calls.
c. Query the call data for audio conference and paging calls.
SELECTuid,src,dst,timestamp,talk_duration,hold_duration,concurrent,dstnameprefix,call_flow,call_type,month,day,hourFROM`cdr`.`cdr_cleaned`WHERE(NOT(dstnameprefix in ('Queue', 'RingGroup')and disposition = 'ANSWERED'))AND (call_flow = 'Audio Conference'OR call_flow = 'Paging'OR dstnameprefix = 'Paging')AND start_ts >= 1774972800000000AND start_ts <= 1777564799999999ORDER BYtimestamp asc,dstnameprefix descLIMIT5000;d. Apply these aggregation rules:
- Paging calls: Treat records that share a
uidas one call; add 1 to device call volume per record; take the call duration only from the Paging record (talk_duration+hold_durationwheredstnameprefix = Paging); base the maximum concurrent calls on the paging record. - Audio conference calls: Treat records that share a
uid_src_dstas one call; add 1 to device call volume per record; take the call duration as the sum oftalk_durationandhold_duration; base the maximum concurrent calls on the aggregated audio conference records.
e. Calculate the call volume, total talk duration, and maximum concurrent calls for device calls within the same period, including multi-party calls.
- Paging calls: Treat records that share a
-
Retrieve data for internal calls.
a. Retrieve internal call data, excluding audio conference and paging calls.
SELECTmax(day) AS time,uid,SUM(talk_duration + hold_duration) as total_talk_duration,MAX(concurrent) as max_concurrent_callFROM`cdr`.`cdr_cleaned`WHEREcall_type = 'Internal'AND src != 'PBX'AND (NOT(dstnameprefix in ('Queue', 'RingGroup')and disposition = 'ANSWERED'))AND call_flow != 'Audio Conference'AND call_flow != 'Paging'AND dstnameprefix != 'Paging'AND start_ts >= 1774972800000000AND start_ts <= 1777564799999999GROUP BY`uid`;b. Calculate the call volume, total talk duration, and maximum concurrent calls for internal calls within the same period, excluding multi-party calls.
c. Query the call data for audio conference and paging calls.
SELECTuid,src,dst,timestamp,talk_duration,hold_duration,concurrent,dstnameprefix,call_flow,call_type,month,day,hourFROM`cdr`.`cdr_cleaned`WHEREcall_type = 'Internal'AND (NOT(dstnameprefix in ('Queue', 'RingGroup')and disposition = 'ANSWERED'))AND (call_flow = 'Audio Conference'OR call_flow = 'Paging'OR dstnameprefix = 'Paging')AND start_ts >= 1774972800000000AND start_ts <= 1777564799999999ORDER BYtimestamp asc,dstnameprefix descLIMIT5000;d. Apply these aggregation rules:
- Paging calls: Treat records that share a
uidas one call; add 1 to internal call volume per record; take the call duration only from the Paging record (talk_duration+hold_durationwheredstnameprefix = Paging); base the maximum concurrent calls on the paging record. - Audio conference calls: Treat records that share a
uid_src_dstas one call; add 1 to internal call volume per record; take the call duration as the sum oftalk_durationandhold_duration; base the maximum concurrent calls on the aggregated audio conference records.
e. Calculate the call volume, total talk duration, and maximum concurrent calls for internal calls within the same period, including multi-party calls.
- Paging calls: Treat records that share a
Transcription Usage Details report
Section titled “Transcription Usage Details report”This report reports total transcription usage grouped by usage type. Retrieve the usage totals from pbx.ai_usage_record.
SELECT usage_type, SUM(duration) as total_durationFROM `pbx`.`ai_usage_record`WHERE ( usage_type in ( 'call_transcription', 'voicemail_transcription' ) ) AND (timestamp >= 1767196800) AND (timestamp < 1779206399)GROUP BY usage_type