MySQL如何按条件统计工单实际所属用户数并查询Top10
解决方案
核心逻辑
统计的核心是先逐行判定每条工单的实际归属用户,规则为:
- 若
hd_forMe = 1,工单归属hd_user字段对应用户 - 若
hd_forMe = 0,工单归属hd_reportedFor字段对应用户,代提交用户不计数
你之前的写法没有提前做这层归属映射,直接按原始提交字段分组、或者用OR条件关联双字段,都会导致计数归属错误、重复计数问题。
基础统计SQL(仅返回有工单的用户Top10)
直接在关联用户表时就用条件判断匹配实际归属人,再分组计数即可:
SELECT COUNT(h.hd_id) AS ticket_count, p.people_id, p.people_firstName, p.people_lastName FROM helpdesk h LEFT JOIN people p ON p.people_id = IF(h.hd_forMe = 1, h.hd_user, h.hd_reportedFor) -- 过滤归属人ID为0的异常数据,业务无异常数据可删除该条件 WHERE IF(h.hd_forMe = 1, h.hd_user, h.hd_reportedFor) != 0 GROUP BY p.people_id, p.people_firstName, p.people_lastName ORDER BY ticket_count DESC LIMIT 10;
针对你给出的样例数据,上述SQL返回结果完全符合预期:
- 用户1:2张工单(匹配hd_id=1、2的自助上报记录)
- 用户2:1张工单(匹配hd_id=3的自助上报记录)
- 用户4:1张工单(匹配hd_id=4的代报记录)
- 用户3无归属工单,不会出现在结果中
扩展:需要展示0工单用户的写法
如果需要把无工单的用户也纳入统计(比如样例中的用户3显示为0),可以以people表为主表,左联提前聚合好的工单子查询,空值补0即可:
SELECT IFNULL(t.ticket_count, 0) AS ticket_count, p.people_id, p.people_firstName, p.people_lastName FROM people p LEFT JOIN ( SELECT IF(h.hd_forMe = 1, h.hd_user, h.hd_reportedFor) AS owner_id, COUNT(h.hd_id) AS ticket_count FROM helpdesk h WHERE IF(h.hd_forMe = 1, h.hd_user, h.hd_reportedFor) != 0 GROUP BY owner_id ) t ON t.owner_id = p.people_id ORDER BY ticket_count DESC LIMIT 10;
原有写法错误说明
- 第一版SQL仅关联
hd_user字段,完全没有处理代报工单归属逻辑,代报工单会被错误算到提交人头上 - 第二版SQL用
OR同时关联提交人和被代报人,会导致同一条代报工单同时匹配两个用户,造成计数重复,且WHERE条件过滤了所有自助上报工单,统计范围本身存在错误
内容的提问来源于stack exchange,提问作者Matthew Barraud
相关产品推荐
相关产品推荐

