Updating and inserting, Duplicate keys - mysql

I've made some changes to this over the last few days and I'm still having issues and unable to produce the correct results.
The following query is for keeping a log of CSR agents by their phone extension and date.
The goal: When this runs throughout the day, it should add any info for extensions not already in the table for the day and update the metrics for the existing ones. If agents 1-5 have been on the phones all day, they're metrics should keep updating and if agent 6 gets on the phones at 3 pm, they should be inserted at that time and update for the rest of the day. However, when the next day starts I want NEW records for all agents to start over, so after 8/8/17, the records for that day should remain and never be overwritten so we can keep a history within this table.
I'm wondering if my problem is with my 'duplicate key update' arguments, but I'm new to that statement so I'm not sure. My primary key is 'Extension', but 'Extension', 'ExtID', and 'Record_date' are all Non NUll. I also put a unique index on 'Extension' and 'Record_date' to make the 'On Duplicate key update' recognize both fields, I"m just not sure it's working.
I just want to update for the current day, and start new records/new inserts on the next day. I.e., if 6 agents work every day for four days, I want the table to have 24 records at the end of the 4th day, I just want the daily records updating throughout.
Thank you for any helpful info. Here's the query:
Insert into test.ambition_test(Extension, ExtID, Total_Talk_Time_seconds,
Total_Talk_Time_minutes,Total_Outbound, Total_Inbound,
Missed_Calls, Total_Calls, Date_of_report, Time_of_report )
SELECT
c.extension as Extension
,RESPONSIBLEUSEREXTENSIONID as ExtID
, sum(Duration) as Total_Talk_Time_seconds
, round(sum(Duration) / 60,2) as Total_Talk_Time_minutes
, sum(if(LEGTYPE1 = 1,1,0)) as Total_Outbound
, sum(if(LEGTYPE1 = 2,1,0)) as Total_Inboundambition_test
, sum(if(Answered = 1,0,1)) as Missed_Calls
, count(DISTINCT b.NOTABLECALLID) as Total_Calls
, date(now())
,NOW()
FROM cdrdb.session a
LEFT JOIN cdrdb.callsummary b
ON a.NOTABLECALLID = b.NOTABLECALLID
LEFT join cdrdb.mxuser c
ON a.RESPONSIBLEUSEREXTENSIONID = c.EXTENSIONID
WHERE b.ts >= curdate()
AND c.extension IN (7295,7306,7218,7247,7330,7000,7358)
group by c.extension
ON duplicate key update Total_Talk_Time_seconds =values(Total_Talk_Time_seconds),
Total_Talk_Time_minutes =values(Total_Talk_Time_minutes),
Total_Outbound = values(Total_Outbound), Total_Inbound = values(Total_Inbound),
Missed_calls = values(Missed_Calls),
Total_Calls = values(Total_Calls),
Date_of_report = values(Date_of_report),
Time_of_report = values(Time_of_report);

I have made some changes on the query, i have modified the aliases and i think it should be ok now. Try it:
Insert into test.ambition_test(Extension, ExtID, Total_Talk_Time_seconds,
Total_Talk_Time_minutes,Total_Outbound, Total_Inbound,
Missed_Calls, Total_Calls, Time_of_report,Date_of_report )
SELECT
c.extension
,RESPONSIBLEUSEREXTENSIONID
, sum(Duration) as Talk_Time_seconds
, round(sum(Duration) / 60,2) as Talk_Time_minutes
, sum(if(LEGTYPE1 = 1,1,0)) as Outbound
, sum(if(LEGTYPE1 = 2,1,0)) as Inbound
, sum(if(Answered = 1,0,1)) as Miss_Calls
, count(DISTINCT b.NOTABLECALLID) as Calls
, NOW()
, curdate()
FROM cdrdb.session a
LEFT JOIN cdrdb.callsummary b
ON a.NOTABLECALLID = b.NOTABLECALLID
LEFT join cdrdb.mxuser c
ON a.RESPONSIBLEUSEREXTENSIONID = c.EXTENSIONID
WHERE b.ts >= curdate()
AND c.extension IN (7295,7306,7218,7247,7330,7000,7358)
group by c.extension
ON duplicate key update Total_Talk_Time_seconds =values(Talk_Time_seconds),
Total_Talk_Time_minutes =values(Talk_Time_minutes),
Total_Outbound = values(Outbound),
Total_Inbound = values(Inbound),
Missed_calls = values(Miss_Calls),
Total_Calls = values(Calls),
Time_of_report = values(NOW());

First of all, you need a column with the day, so you can have a record for each day in the table test.ambition_test of type DATE (no DATETIME). I supose you have created it and it´s called Record_Date.
Then you need to make a unique index on the table test.ambition_test on the columns (Extension, Record_Date) (It will be ok if you make it primary key. You need to make sure that you don´t have another unique key on that table. You can have more indexes, but not unique (neither primary keys).
Then you can use the insert clause. See that i have changed the now() instruction by DATE(NOW()) so you only get the day.
In the query, you use Time_of_report, that i think it should be Record_Date (it must be the same that you have in the index)
Insert into test.ambition_test(Extension, ExtID, Total_Talk_Time_seconds,
Total_Talk_Time_minutes,Total_Outbound, Total_Inbound,
Missed_Calls, Total_Calls, Time_of_report,Date_of_report )
SELECT
c.extension as Extension
,RESPONSIBLEUSEREXTENSIONID as ExtID
, sum(Duration) as Total_Talk_Time_seconds
, round(sum(Duration) / 60,2) as Total_Talk_Time_minutes
, sum(if(LEGTYPE1 = 1,1,0)) as Total_Outbound
, sum(if(LEGTYPE1 = 2,1,0)) as Total_Inboundambition_test
, sum(if(Answered = 1,0,1)) as Missed_Calls
, count(DISTINCT b.NOTABLECALLID) as Total_Calls
, NOW()
, DATE(NOW())
FROM cdrdb.session a
LEFT JOIN cdrdb.callsummary b
ON a.NOTABLECALLID = b.NOTABLECALLID
LEFT join cdrdb.mxuser c
ON a.RESPONSIBLEUSEREXTENSIONID = c.EXTENSIONID
WHERE b.ts >= curdate()
AND c.extension IN (7295,7306,7218,7247,7330,7000,7358)
group by c.extension
ON duplicate key update Total_Talk_Time_seconds =values(Total_Talk_Time_seconds),
Total_Talk_Time_minutes =values(Total_Talk_Time_minutes),
Total_Outbound = values(Total_Outbound), Total_Inbound = values(Total_Inbound),
Missed_calls = values(Missed_Calls),
Total_Calls = values(Total_Calls),
Time_of_report = values(Time_of_report);

Related

Modifying query to use a new table in place of a static range of numbers

I have a working query (shown below) that I'm trying to consolidate and use another table for a more direct approach but I'm not quite sure how to go about this.
First, Here's the query:
select
case
when callingpartyno in (7276,7314,7295,7306,7357,7200,7218,7247,7331,7255,7330,7000,7215,7240,7358,7312)
then callingpartyno
when finallycalledpartyno in (7276,7314,7295,7306,7357,7200,7218,7247,7331,7255,7330,7000,7215,7240,7358,7312)
then finallycalledpartyno
end as id
, sum(duration) as total_talk_time_seconds
, round(sum(duration) / 60,2) as total_talk_time_minutes
, sum(if(legtype1 = 1,1,0)) as total_outbound
, sum(if(legtype1 = 2,1,0) and answered = 1) as total_inbound
, sum(if(legtype1 = 2,1,0) and answered = 0) as total_missed
, sum(if(legtype1 = 1, 1, 0)) + -- outbound calls
sum(if(legtype1 = 2, 1, 0)) as total_calls
, now() as time_of_report
, curdate() as date_of_report
from
ambition.session a
join ambition.callsummary b
on a.notablecallid = b.notablecallid
where
date(b.ts) >= curdate()
and (
callingpartyno in (7276,7314,7295,7306,7357,7200,7218,7247,7331,7255,7330,7000,7215,7240,7358,7312
)
or finallycalledpartyno in (7276,7314,7295,7306,7357,7200,7218,7247,7331,7255,7330,7000,7215,7240,7358,7312
)
)
group by
id;
Instead of looking for callingpartyno and finallycalledpartyno in that range of 16 numbers, I made a table called users that houses the 4-digit extensions and the first/last name of the agents. I want to join that table and use it to display the names and extensions of the users instead.
The table structure is:
ambition.users
ID PK NN INT
extension INT
firstn varchar
lastn varchar
So I basically want to change my query to say "When callingpartyno/finallycalledpartyno in u.extension" etc.
Which type of joing would I need to do to match what I have in the existing query, and how would I structure it to keep the results the same just using a new table instead of a range?
I would expect something like this:
select uc.agent as calling_agent, uf.agent as final_agent,
sum(duration) as total_talk_time_seconds,
round(sum(duration) / 60, 2) as total_talk_time_minutes,
sum(legtype1 = 1) as total_outbound,
sum(legtype1 = 2 and answered = 1) as total_inbound,
sum(legtype1 = 2 and answered = 0) as total_missed,
sum(legtype1 = 1) + -- outbound calls
sum(legtype1 = 2) as total_calls,
now() as time_of_report,
curdate() as date_of_report
from ambition.session s join
ambition.callsummary cs
on s.notablecallid = cs.notablecallid left join
users uc
on ?.callingpartyno = uc.extension left join
users uf
on ?.finallycalledpartyno = uf.extension
where date(b.ts) >= curdate() and
(uc.extension is not null or uf.extension is not null)
group by calling_agent, final_agent;
The ? are for the names of the corresponding tables and columns.

Grouping my multiple columns for a single condiiton

I have a query below that's working but not quite how I want it.
The query pulls phone data for our CSRs and we're currently getting data for 15 agents. The current query gets the totals I need but adds them all up and gives me one line of totals. I'd like to have it showing totals for each CSR. The problem with this is that each call record in the source table has their 4-digit extension as either the calling number or the called number. However, there is no one field that exists in each record to tie that user's extension to the call. It either has to exist as the calling or called number.
So I've got the logic worked out correctly, I believe, except that now I need to group calls by extension. So with 15 CSRs, I want the statement to return 15 rows, each with their own individual totals. But since there's no universal field to group by, I think I would need to group by both fields.
In other words, say "If callingpartyno has 7200 and finallycalledpartyno has 7200, group these as the totals for extension 7200".
Here's an example of how the data looks in the source table:
callingpartyno | finallycalledpartyno
-------------------------------------
1234 outside
1234 outside
1234 outside
outsidecall 1234
outsidecall 1234
outsidecall 1234
9876 outside
9876 outside
9876 outside
outsidecall 9876
outsidecall 9876
outsidecall 9876
As you can see, nothing identifies each record to the same CSR.
And here is the query:
SELECT
sum(Duration) AS total_talk_time_seconds
, round(sum(Duration) / 60,2) AS total_talk_time_minutes
, sum(if(LEGTYPE1 = 1,1,0)) AS total_outbound
, sum(if(LEGTYPE1 = 2,1,0) and ANSWERED = 1) AS total_inbound
, sum(if(LEGTYPE1 = 2,1,0) and ANSWERED = 0) AS total_missed
, SUM(IF(LEGTYPE1 = 1, 1, 0)) + -- outbound calls
SUM(IF(LEGTYPE1 = 2, 1, 0)) AS total_calls
, NOW() AS time_of_report
, curdate() AS date_of_report
FROM cdrdb.session a
INNER JOIN cdrdb.callsummary b
ON a.NOTABLECALLID = b.NOTABLECALLID
where date(b.ts) = '2017-10-16 00:00:00'
AND callingpartyno IN (7276,7314, 7295, 7306,7357,7200,7218,7247 7331,7255,7330,7000,7215, 7240,7358,7312)
OR finallycalledpartyno IN (7276,7314, 7295, 7306,7357,7200,7218,7247 7331,7255,7330,7000,7215, 7240,7358,7312)
So again, the query works to pull records for the specified date, where any of those extensions are in either callingpartyno or finallycalledpartyno, but I need a way to group it by those two and treat each record as the 4-digit extension, almost like a user ID.
This is exactly what the group by clause is for. By inserting a case statement, we can create an ID using your own conditions.
select
case
when callingpartyno in (7276,7314,7295,7306,7357,7200,7218,7247,7331,7255,7330,7000,7215,7240,7358,7312)
then callingpartyno
when finallycalledpartyno in (7276,7314,7295,7306,7357,7200,7218,7247,7331,7255,7330,7000,7215,7240,7358,7312)
then finallycalledpartyno
end as id
, sum(duration) as total_talk_time_seconds
, round(sum(duration) / 60,2) as total_talk_time_minutes
, sum(if(legtype1 = 1,1,0)) as total_outbound
, sum(if(legtype1 = 2,1,0) and answered = 1) as total_inbound
, sum(if(legtype1 = 2,1,0) and answered = 0) as total_missed
, sum(if(legtype1 = 1, 1, 0)) + -- outbound calls
sum(if(legtype1 = 2, 1, 0)) as total_calls
, now() as time_of_report
, curdate() as date_of_report
from
cdrdb.session a
join cdrdb.callsummary b
on a.notablecallid = b.notablecallid
where
date(b.ts) = '2017-10-16 00:00:00'
and (
callingpartyno in (7276,7314,7295,7306,7357,7200,7218,7247,7331,7255,7330,7000,7215,7240,7358,7312)
or finallycalledpartyno in (7276,7314,7295,7306,7357,7200,7218,7247,7331,7255,7330,7000,7215,7240,7358,7312)
)
group by
id -- <-- the calculated field we created in the select clause
I've also corrected your or statement. Using it outside of parenthesis like you did made the date more or less irrelevant.
I would suggest:
SELECT sum(Duration) AS total_talk_time_seconds,
round(sum(Duration) / 60, 2) AS total_talk_time_minutes,
sum(LEGTYPE1 = 1) AS total_outbound,
sum(LEGTYPE1 = 2 and ANSWERED = 1) AS total_inbound,
sum(LEGTYPE1 = 2 and ANSWERED = 0) AS total_missed,
SUM(LEGTYPE1 in (1, 2)) AS total_calls,
NOW() AS time_of_report,
curdate() AS date_of_report
FROM cdrdb.session s INNER JOIN
cdrdb.callsummary cs
ON s.NOTABLECALLID = cs.NOTABLECALLID
where date(b.ts) = '2017-10-16' and
(callingpartyno IN (7276, 7314, 7295, 7306, 7357, 7200,7218,7247, 7331, 7255, 7330, 7000, 7215, 7240,7358,7312) or
finallycalledpartyno IN (7276,7314, 7295, 7306,7357,7200, 7218,7247, 7331, 7255, 7330, 7000, 7215, 7240, 7358, 7312)
)
group by (case when callingpartyno IN (7276, 7314, 7295, 7306,7357, 7200, 7218, 7247, 7331,7255,7330,7000,7215, 7240,7358,7312)
then callingpartyno else finallycalledpartyno
end);
Your real problem are the parentheses around the logic in the where clause.
In addition, I made the following changes:
Removed the if(). If you are going to use MySQL extensions, just use the extension that treats booleans as integers.
Use in instead of chained comparisons
No need to include the time component of a date in the string literal.

Combining conditions for CASE, mysql query

I'm trying to finish up a query to total different numbers for our people on the phones and I have the standard totals calculated fine, it seems, but I'm now trying to do this:
For every total column (total calls, total inbound, total outbound, total missed) I now need to have a new column partnered with it for known numbers in our database (so I'll have total calls known, total inbound known, etc.).
The way I'm doing this is by checking two fields in my session table: callingpartyno and finallycalledpartyno. So, for every call in session I need to check to see if the number in either of those fields are in my knownNumbers table in the phone_number field. If so, I need to count them for the known column.
About 8 lines down in my query below, I have my first instance of this which seems to be showing accurate numbers, but it's only incorporating callingpartyno. I first need to know how to combine conditions in this 'case whento addfinallycalledpartyno` as well.
The other issue is that for inbound and outbound, I need to base the phone number field I'm using on the LEGTYPE field. So, for example, IF I'm calculating outbound calls to known numbers I need something like
sum(if(LEGTYPE1 = 1,1,0)) AND finallycalledpartno = k.phone_number AS Total_Outbound_known.
I hope this makes sense, and it should be pretty straightforward for an advanced SQL programmer. I just can't seem to get the combination of conditions in a case when statement to work especially.
Query below:
SELECT u.firstn
,u.lastn
,c.extension
,SUM(IF(LEGTYPE1 = 1, 1, 0)) + -- outbound calls
SUM(IF(LEGTYPE1 = 2, 1, 0) AND ANSWERED = 1) + -- inbound calls
SUM(IF(Answered = 1, 0, 1)) AS Total_Calls
,sum(case when CALLINGPARTYNO = k.phone_number then 1 else 0 end ) AS total_known
,sum(if(Answered = 1,0,1)) AS Total_Missed
,sum(if(LEGTYPE1 = 2,1,0) and ANSWERED = 1) AS Total_Recieved
,sum(if(LEGTYPE1 = 1,1,0)) AS Total_Outbound
,round(sum(Duration) / 60,2) AS Total_Talk_Time_minutes
,sum(if(Answered = 1,0,1)) / (SUM(IF(LEGTYPE1 = 1, 1, 0)) + -- outbound calls
SUM(IF(LEGTYPE1 = 2, 1, 0) AND ANSWERED = 1) + -- inbound calls
SUM(IF(Answered = 1, 0, 1))) * 100 AS Percentage_Missed
FROM ambition.session a
INNER JOIN ambition.callsummary b
ON a.NOTABLECALLID = b.NOTABLECALLID
INNER join ambition.mxuser c
ON a.RESPONSIBLEUSEREXTENSIONID = c.EXTENSIONID
INNER join jackson_id.users u
on c.extension = u.extension
left join ambition.knownnumbers k
on a.callingpartyno = k.phone_number
WHERE b.ts between curdate() - interval 5 day and now()
AND c.extension IN (7276,7314,7295,7306,7357,7200,7218,7247,7331,7255,7330,7000,7215,7240,7358,7312)
group by c.extension;
Apart what I wrote in above comments, I would rewrite your query like this (I think at least it should be easier to read it, avoiding to repeat some SUMs)
SELECT firstn
, lastn
, extension
, Total_Outbound+Total_Missed+Total_Received AS Total_Calls
, Total_Known
, Total_Missed
, Total_Received
, Total_Outbound
, Total_Talk_Time_minutes
, Total_Missed / (Total_Outbound+Total_Missed+Total_Received) * 100 AS Percentage_Missed
FROM (
SELECT u.firstn
, u.lastn
, c.extension
, sum(case when CALLINGPARTYNO = k.phone_number then 1 else 0 end ) AS Total_Known
, sum(if(Answered = 1,0,1)) AS Total_Missed
, sum(CASE WHEN LEGTYPE1 = 2 AND ANSWERED = 1 THEN 1 ELSE 0 END) AS Total_Received
, sum(if(LEGTYPE1 = 1,1,0)) AS Total_Outbound
, round(sum(Duration) / 60,2) AS Total_Talk_Time_minutes
FROM ambition.session a
INNER JOIN ambition.callsummary b ON a.NOTABLECALLID = b.NOTABLECALLID
INNER join ambition.mxuser c ON a.RESPONSIBLEUSEREXTENSIONID = c.EXTENSIONID
INNER join jackson_id.users u ON c.extension = u.extension
LEFT JOIN ambition.knownnumbers k ON a.callingpartyno = k.phone_number
WHERE b.ts between curdate() - interval 5 day and now()
AND c.extension IN (7276,7314,7295,7306,7357,7200,7218,7247,7331,7255,7330,7000,7215,7240,7358,7312)
GROUP BY c.extension, u.firstn, u.lastn
) X;

Sum/count with a where/if statement to find existing value

I'm building a table to use for weekly reports but I'm starting with queries to get an idea of the data first.
Below I have my main query, which is working for my main totals currently, but my existing 'Total' columns need a partner column which will display a different total. Basically, this is all in relation to phone calls, so currently I have phone totals (total calls, total missed, total inbound, total outbound) but I need an additional column for each that counts the amount of calls that were to/from known numbers in our database.
I have a table called ambition.ambition_customer_data with a field called phone_number. So, if you look about 8 lines down in my query I need to get a sum or count for numbers where calledpartyno = ambition_customer_data.phone_number OR finallycalledpartyno = ambition_customer_data.phone_number if that makes sense.
For the other columns, I'll need to do the same but I will have to base it on the legtype column seen below, but If I have an idea of how to do this first I can apply it to those. I was hoping I could do a SUM(WHERE calledpartyno IN (select phone_number from ambition_customer_data)) but that doesn't seem to work.
I currently have an incomplete IF statement. Any tips on the best way I can do this?
SELECT
u.firstn
, u.lastn
, c.extension
, SUM(IF(LEGTYPE1 = 1, 1, 0)) + -- outbound calls
SUM(IF(LEGTYPE1 = 2, 1, 0) AND ANSWERED = 1) + -- inbound calls
SUM(IF(Answered = 1, 0, 1)) AS Total_Calls
, sum(if calledpartyno =) /*HERE IS MY ISSUE CURRENTLY*/
, sum(if(Answered = 1,0,1)) AS Total_Missed
, sum(if(LEGTYPE1 = 2,1,0) and ANSWERED = 1) AS Total_Recieved
, sum(if(LEGTYPE1 = 1,1,0)) AS Total_Outbound
, round(sum(Duration) / 60,2) AS Total_Talk_Time_minutes
, sum(if(Answered = 1,0,1)) / (SUM(IF(LEGTYPE1 = 1, 1, 0)) + -- outbound calls
SUM(IF(LEGTYPE1 = 2, 1, 0) AND ANSWERED = 1) + -- inbound calls
SUM(IF(Answered = 1, 0, 1))) * 100 AS Percentage_Missed
FROM ambition.session a
INNER JOIN ambition.callsummary b
ON a.NOTABLECALLID = b.NOTABLECALLID
INNER join ambition.mxuser c
ON a.RESPONSIBLEUSEREXTENSIONID = c.EXTENSIONID
INNER join jackson_id.users u
on c.extension = u.extension
WHERE b.ts between curdate() - interval 5 day and now()
AND c.extension IN (7276,7314,7295,7306,7357,7200,7218,7247,7331,7255,7330,7000,7215,7240,7358,7312)
group by c.extension;
You're looking for something like this.
SUM(CASE WHEN CONDITION_HERE THEN COLUMN_TO_SELECT END) AS `SELECTION_NAME`

Expressing formula within a SELECT query

I have this existing query:
SELECT
extension
, Total_Outbound+Total_Missed+Total_Received AS Total_Calls
, Total_Missed
, Total_Talk_Time_minutes
FROM (
SELECT
, extension
, sum(if(Answered = 1,0,1)) AS Total_Missed
, sum(CASE WHEN LEGTYPE1 = 2 AND ANSWERED = 1 THEN 1 ELSE 0 END) AS Total_Received
, sum(if(LEGTYPE1 = 1,1,0)) AS Total_Outbound
, round(sum(Duration) / 60,2) AS Total_Talk_Time_minutes
FROM session a
GROUP BY extension
) x;
It works great but I need to add a metric/formula to it called missed_call_score right under Total_Talk_Time_Minutes.
The formula for the missed call score is this:
(missed calls/total talk time) * (average calls per CSR/total calls) * 100 but one thing to note is that the average calls per csr needs to ignore the MAX and MIN, so the lowest and highest number of calls taken.
I'm not sure how I could construct this score within a single select variable or the syntax I would use for this given the fact that it has to throw out the max and min.
Here is an example of my needed output and the formulas it should be using:
extension | Total calls | missed calls | total talk time | missed call score
----------------------------------------------------------------------------
1234 8 4 15.5 5.7
4321 4 0 9.42 0.0
5678 5 2 6.78 6.5
9876 13 6 18.3 7.2
Total call sum = 30
Total call sum without high and low = 13
average calls per CSR = (13/2) = 6.5
extension 1 = (4/15.5) * (6.5/30) * 100 = 5.7
extension 2 = (0/9.42) * (6.5/30) * 100 = 0.0
extension 3 = (2/6.78) * (6.5/30) * 100 = 6.5
extension 4 = (6/18.3) * (6.5/30) * 100 = 7.2
The data above for extension, total calls, missed calls and talk time are taken from my sql fiddle, linked below. I simply added the score column to give example of my expected output.
The fiddle linked below shows my create and inserts so hopefully that gives everything needed to assist me with this.
**sql fiddle
**
http://sqlfiddle.com/#!9/aa1f9/1
UPDATE
Full production query with joins
SELECT firstn ,
lastn ,
extension ,
Total_Outbound+Total_Missed+Total_Received AS Total_Calls ,
Total_Missed ,
Total_Talk_Time_minutes ,
Total_All_Calls ,
Max_Calls ,
Min_Calls ,
CSR_Count ,
((Total_Missed/Total_Talk_Time_minutes) *
(((Total_All_Calls-Max_Calls-Min_Calls)/CSR_Count)/Total_All_Calls)) * 100
FROM ( SELECT u.firstn ,
u.lastn ,
c.extension ,
sum(if(Answered = 1,0,1)) AS Total_Missed ,
sum(CASE WHEN LEGTYPE1 = 2 AND ANSWERED = 1 THEN 1 ELSE 0 END) AS Total_Received ,
sum(CASE WHEN LEGTYPE1 = 1 THEN 1 ELSE 0 END) AS Total_Outbound ,
round(sum(Duration) / 60,2) AS Total_Talk_Time_minutes ,
(SELECT COUNT(1) FROM ambition.session a INNER JOIN ambition.callsummary b ON a.NOTABLECALLID = b.NOTABLECALLID
INNER join ambition.mxuser c ON a.RESPONSIBLEUSEREXTENSIONID = c.EXTENSIONID
INNER join jackson_id.users u ON c.extension = u.extension
WHERE b.ts between curdate() - interval 5 day and now()
AND c.extension IN (7276,7314,7295,7306,7357,7200,7218,7247,7331,7255,7330,7000,7215,7240,7358,7312)) Total_All_Calls ,
(SELECT MAX(CNT) FROM (SELECT COUNT(1) CNT, c.extension
FROM ambition.SESSION a INNER JOIN ambition.callsummary b ON a.NOTABLECALLID = b.NOTABLECALLID
INNER join ambition.mxuser c ON a.RESPONSIBLEUSEREXTENSIONID = c.EXTENSIONID
INNER join jackson_id.users u ON c.extension = u.extension
WHERE b.ts between curdate() - interval 5 day and now()
AND c.extension IN (7276,7314,7295,7306,7357,7200,7218,7247,7331,7255,7330,7000,7215,7240,7358,7312) GROUP BY responsibleuserextensionid) y) Max_Calls ,
(SELECT MIN(CNT) FROM (SELECT COUNT(1) CNT, c.extension
FROM ambition.SESSION a
INNER JOIN ambition.callsummary b ON a.NOTABLECALLID = b.NOTABLECALLID
INNER join ambition.mxuser c ON a.RESPONSIBLEUSEREXTENSIONID = c.EXTENSIONID
INNER join jackson_id.users u ON c.extension = u.extension
WHERE b.ts between curdate() - interval 5 day and now()
AND c.extension IN (7276,7314,7295,7306,7357,7200,7218,7247,7331,7255,7330,7000,7215,7240,7358,7312)GROUP BY responsibleuserextensionid) y) Min_Calls ,
(SELECT COUNT(DISTINCT c.extension)-2
FROM ambition.SESSION a INNER JOIN ambition.callsummary b ON a.NOTABLECALLID = b.NOTABLECALLID
INNER join ambition.mxuser c ON a.RESPONSIBLEUSEREXTENSIONID = c.EXTENSIONID
INNER join jackson_id.users u ON c.extension = u.extension
WHERE b.ts between curdate() - interval 5 day and now()
AND c.extension IN (7276,7314,7295,7306,7357,7200,7218,7247,7331,7255,7330,7000,7215,7240,7358,7312)) CSR_Count
FROM ambition.session a
INNER JOIN ambition.callsummary b ON a.NOTABLECALLID = b.NOTABLECALLID
INNER join ambition.mxuser c ON a.RESPONSIBLEUSEREXTENSIONID = c.EXTENSIONID
INNER join jackson_id.users u ON c.extension = u.extension
LEFT JOIN ambition.knownnumbers k ON a.callingpartyno = k.phone_number
WHERE b.ts between curdate() - interval 5 day and now()
AND c.extension IN (7276,7314,7295,7306,7357,7200,7218,7247,7331,7255,7330,7000,7215,7240,7358,7312)
GROUP BY c.extension, u.firstn, u.lastn ) x
This should work for you:
SELECT
extension
, Total_Outbound+Total_Missed+Total_Received AS Total_Calls
, Total_Missed
, Total_Talk_Time_minutes
, Total_All_Calls
, Max_Calls
, Min_Calls
, CSR_Count
, ((Total_Missed/Total_Talk_Time_minutes) *
(((Total_All_Calls-Max_Calls-Min_Calls)/CSR_Count)/Total_All_Calls)) * 100
FROM (
SELECT
extension
, sum(if(Answered = 1,0,1)) AS Total_Missed
, sum(CASE WHEN LEGTYPE1 = 2 AND ANSWERED = 1 THEN 1 ELSE 0 END) AS Total_Received
, sum(CASE WHEN ANSWERED = 1 AND LEGTYPE1 = 1 THEN 1 ELSE 0 END) AS Total_Outbound
, round(sum(Duration) / 60,2) AS Total_Talk_Time_minutes
, (SELECT COUNT(1) FROM session) Total_All_Calls
, (SELECT MAX(CNT) FROM (SELECT COUNT(1) CNT, EXTENSION FROM SESSION GROUP BY EXTENSION) y) Max_Calls
, (SELECT MIN(CNT) FROM (SELECT COUNT(1) CNT, EXTENSION FROM SESSION GROUP BY EXTENSION) y) Min_Calls
, (SELECT COUNT(DISTINCT EXTENSION)-2 FROM SESSION) CSR_Count
FROM session a
GROUP BY extension
) x;
Here is the fiddle.
Basically I used sub-counts in your derived table x to get each of the variables needed for missed_call_score. One major thing worth noting is that the logic was off for Total_Outbound, so I tweaked that to a CASE statement instead of an IF(). I selected the count columns in the outer query just so you can see what is going on, you can remove those.
I've done something similar in the past and extracted this snippet from my code.
I think/hope that this might help you getting started (I left out most of the columns from your query and you'd have to adjust avg(amount) to match your formula.
select extension, avg(amount) from
(
select t.*,
min(amount) over (partition by extension) as min_amt,
max(amount) over (partition by extension) as max_amt
from your_table t
) t
where amount > min_amt and amount < max_amt group by extension;