Group by Count of (Top 5) & Count of (All Other)

守給你的承諾、 提交于 2020-01-16 05:21:06

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!