You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQLZoo HelpDesk问题:WHERE语句筛选前20%呼叫者的逻辑疑问

SQLZoo HelpDesk项目:80/20法则SQL语句WHERE子句逻辑解析

问题背景

我正在完成SQLZoo的HelpDesk项目,针对「验证80/20法则:统计最活跃20%呼叫者的呼叫占比」问题,找到了如下SQL解决方案,但无法理解最后一行WHERE语句的逻辑:

SELECT ROUND(SUM(b.calls_per_caller / (SELECT COUNT(*) FROM Issue) * 100), 4) as t20pc
FROM (
   SELECT a.*, @counter := @counter + 1 AS counter
   FROM
      (SELECT @counter := 0) AS initvar,
      (SELECT caller_id, COUNT(*) AS calls_per_caller
         FROM Issue
         GROUP BY caller_id
         ORDER BY COUNT(*) DESC) AS a
) AS b
WHERE counter <= (20/100 * @counter)

我对@counter和counter的区别及其中的数学逻辑存在疑问:例如假设counter为30时,30<=6不成立;counter为10时,10<=2也不成立,但代码实际能得到正确结果。想请教该WHERE语句如何确保仅筛选出最活跃的20%呼叫者?


逻辑拆解

1. @counter与counter的本质区别

  • @counter是全局用户变量:
    初始通过(SELECT @counter := 0) AS initvar赋值为0,之后在遍历排序后的呼叫者列表时,每处理一行就执行@counter := @counter + 1,等整个子查询b执行完毕,@counter的值等于系统中所有呼叫者的总数量。
  • counter是行级序号字段:
    它是每行的临时字段,值为当前行处理时@counter自增后的结果,代表该呼叫者的活跃度排名(呼叫量越高,排名越靠前,从1开始计数)。

2. WHERE子句的实际运行逻辑

你觉得矛盾是因为误解了@counter的取值时机:MySQL的查询执行顺序是先完成内层子查询b的所有计算,此时@counter已经固定为总呼叫者数,之后才会执行外层的WHERE筛选。

举个实际例子:
如果系统里总共有100个呼叫者,子查询b执行完后@counter的值是100,那么20/100 * @counter的结果就是20。此时WHERE条件变为counter <=20,直接筛选出排名前20的活跃呼叫者,统计他们的呼叫占比,完全符合80/20法则的验证需求。

你之前假设的counter=30时30<=6的情况不会出现——因为此时@counter是总呼叫者数(比如150),20%的计算结果是30,条件就变成30<=30,是成立的。


内容的提问来源于stack exchange,提问作者Anthony Garces

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 21:32:55