SQL竞赛用户参与占比异常:非100%结果显示为0问题排查
问题解决方法
核心问题分析
你的SQL得到0.0的结果,主要是两个原因:
- 整数除法陷阱:
COUNT(DISTINCT user_id)和(select count(user_id) from users)都是整数,SQL中整数除法会直接舍去小数部分(比如2/3=0),后续加0.0再乘100也无法改变这个初始结果。 - 字段类型不匹配:
register表的user_id是Varchar类型,users表的是Int类型,直接统计可能存在隐性类型转换导致的统计偏差。
修正后的SQL
SELECT contest_id, ROUND( (COUNT(DISTINCT CAST(user_id AS UNSIGNED)) * 100.0) / (SELECT COUNT(user_id) FROM users), 2 ) AS percentage FROM register GROUP BY contest_id ORDER BY percentage DESC, contest_id ASC;
关键调整说明
- 类型统一:用
CAST(user_id AS UNSIGNED)将register表的字符串类型user_id转为整数,确保统计的是与users表匹配的有效用户,避免类型不匹配导致的错误统计。 - 浮点数运算:先乘
100.0将分子转为浮点数,这样后续除法会以浮点数计算,避免整数除法的截断问题。 - 保留小数:用
ROUND(...,2)直接将结果保留两位小数,符合需求。 - 排序规则:补充
contest_id ASC,满足“占比降序、竞赛ID升序”的排序要求。
另一种等价写法
如果习惯先转换分母,也可以这么写:
SELECT contest_id, ROUND( COUNT(DISTINCT CAST(user_id AS UNSIGNED)) / (SELECT CAST(COUNT(user_id) AS FLOAT)) * 100, 2 ) AS percentage FROM register GROUP BY contest_id ORDER BY percentage DESC, contest_id ASC;
内容的提问来源于stack exchange,提问作者Ale
相关产品推荐
相关产品推荐

