I'm hoping this is just an error in my formatting so i won't post more of my query than necessary.
I had a large query with multiple joins and several SUM arguments (the point of this query is to aggregate daily totals every time it gets ran).
This is my trouble line:
sum(case when (duration > 60 and LEGTYPE1 = 1) then 1 else 0 end)
I also tried this:
count(case when (duration > 60 and LEGTYPE1 = 1) then 1 else null end)
Here's the problem: The sum case returns either a 1 or 0, and the count line does return the count (13,14,16) but it's not the right number for my records.
Here's the whole query for context:
SELECT c.extension
, 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(Answered = 1,0,1)) AS Total_Missed
, 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
, NOW() AS Time_of_report
, curdate() AS Date_of_report
FROM cdrdb.session a
INNER JOIN cdrdb.callsummary b
ON a.NOTABLECALLID = b.NOTABLECALLID
INNER join cdrdb.mxuser c
ON a.RESPONSIBLEUSEREXTENSIONID = c.EXTENSIONID
WHERE b.ts >= curdate()
AND c.extension IN (7276,7314,7295,7306,7357,7200,7218,7247,7331,7255,7330,7000,7215,7240,7358,7312)
group by c.extension
SO, when I do the count version of that line, the number matches the total number of calls, where it should only represent the outbound ones that last longer than 60 seconds. The data is correct and the fields are correct, I'm simply asking if my syntax is correct or if there's simply a better way to structure it.
Not sure I follow your logic but:
sum(if(LEGTYPE1 = 2,1,0) and ANSWERED = 1) AS Total_Inbound
and
SUM(IF(LEGTYPE1 = 2, 1, 0) AND ANSWERED = 1) +
SUM(IF(Answered = 1, 0, 1)) AS Total_Calls
Seem wrong. Try:
sum(if(LEGTYPE1 = 2 and ANSWERED = 1, 1, 0) AS Total_Inbound
and
SUM(IF(LEGTYPE1 = 2 AND ANSWERED =1 , 1, 0) +
IF(Answered = 1, 0, 1)
) AS Total_Calls
Related
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.
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.
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;
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`
I'm trying the query below and MySQL gave me this error: Invalid use of group function
SELECT C.`some_name`,
SUM(IF(A.`med_type` = 1, SUM(A.`med_qty`), 0)) AS total,
SUM(IF(A.`is_rejected` = 4, 1 , 0)) AS approved,
SUM(IF(A.`is_rejected` = 2, 1 , 0)) AS qeue,
SUM(IF(A.`is_rejected` = 3, 1 , 0)) AS rejected,
SUM(IF(A.`is_rejected` = 1, 1 , 0)) AS fresh
FROM `ne_media` A
INNER JOIN `ne_member` B ON A.`mem_id` = B.`mem_id`
INNER JOIN `ne_some` C ON B.`some_id` = C.`some_id`
GROUP BY C.`some_id`;
I want to sum med_qty just if med_type = 1.
How do I do it?
Use:
SUM(CASE WHEN (A.`med_type` = 1) THEN A.`med_qty` ELSE 0 END)) AS total,
or:
SUM(IF(A.`med_type` = 1, A.`med_qty`, 0)) AS total,
You can't do aggregates on aggregates like you tried to in the original.