问题
I have a query that I need to edit. Currently, it returns 2 columns of data, a case label and the count (or total number of cases) handled during the previous 7 day period starting yesterday. I need to change this output so that only 6 labels are in the output (i.e - always 6 rows of data). These rows need to be the top 5 labels and the sum of the remaining labels as the 6th label (called "Other"). This is because this output is fed to a PHP script that presents the data on a web-based platform.
Finally, to illustrate here is a table of the output I need as well as the query below.
+-----------+---------------+
| CaseLabel | CasesResolved |
+-----------+---------------+
| Label1 | 20 |
| Label2 | 18 |
| Label3 | 10 |
| Label4 | 9 |
| Label5 | 7 |
| Other | 12 |
+-----------+---------------+
Thanks in advance for any help! :-)
Running MySQL 5.096
MySQL Code:
SELECT
deskcases.Labels,
COUNT(deskcases.Labels)AS CaseCount
FROM
deskcases
WHERE
deskcases.Labels NOT LIKE ''
AND deskcases.Labels NOT LIKE '%SPAM%'
AND deskcases.Labels NOT LIKE '%Online Orders%'
AND deskcases.Labels NOT LIKE '%Internal SPAM%'
AND deskcases.`Case Status` LIKE 'Resolved'
AND deskcases.`Resolved At` > CURDATE()- INTERVAL 7 DAY
GROUP BY
deskcases.Labels
ORDER BY
CaseCount DESC
回答1:
In MySQL, probably the easiest way to express this is by using a temporary table:
create temporary table temp as (
id int not null auto_increment,
CaseLabel varchar(255),
CasesResolved int
);
insert into temp(CaseLabel, CasesResolved)
SELECT deskcases.Labels, COUNT(deskcases.Labels)AS CaseCount
FROM deskcases
WHERE deskcases.Labels NOT LIKE ''
AND deskcases.Labels NOT LIKE '%SPAM%'
AND deskcases.Labels NOT LIKE '%Online Orders%'
AND deskcases.Labels NOT LIKE '%Internal SPAM%'
AND deskcases.`Case Status` LIKE 'Resolved'
AND deskcases.`Resolved At` > CURDATE()- INTERVAL 7 DAY
GROUP BY deskcases.Labels
ORDER BY CaseCount DESC;
select (case when id <= 5 then caselabel else 'Other' end),
SUM(casesResolved) as CasesResolved
from temp
group by (case when id <= 5 then caselabel else 'Other' end)
order by MAX(id) desc
The id
column in the temporary table adds a row number onto each row. In any other real database, you would use the row_number()
function, but MySQL does not support that.
回答2:
One possible option is to use a rank variable.
The dummy join will initialize the rank and the if will count up to 6.
All this stuff will first get resolved in the inner query, producing stuff like
| Label1 | 20 |
| Label2 | 18 |
| Label3 | 10 |
| Label4 | 9 |
| Label5 | 7 |
| Label6 | 12 |
| Label7 | |
| ......
The other query will then collapse this into the desired output.
select if(rank=6,"Other",sub.Labels) as Label, SUM(sub.CaseCount) from (
SELECT
if(@Rank < 6,@Rank:= @Rank + 1, @Rank) as Rank
,deskcases.Labels
,COUNT(deskcases.Labels) AS CaseCount
FROM
deskcases
JOIN (@rank:= 0)
WHERE
deskcases.Labels NOT LIKE ''
AND deskcases.Labels NOT LIKE '%SPAM%'
AND deskcases.Labels NOT LIKE '%Online Orders%'
AND deskcases.Labels NOT LIKE '%Internal SPAM%'
AND deskcases.`Case Status` LIKE 'Resolved'
AND deskcases.`Resolved At` > CURDATE()- INTERVAL 7 DAY
GROUP BY
deskcases.Labels
ORDER BY
CaseCount DESC
) sub
group by sub.rank ASC
Replacing the labelx
into "Other" for the last line.
来源:https://stackoverflow.com/questions/15531942/group-by-count-of-top-5-count-of-all-other