如何用SQL计算同时存在于两个表中的用户占比?
计算跨表用户的占比
需求说明
需要统计同时出现在users和offers表中的用户数占users表总用户数的比例,你已经能通过内连接找出共同用户,现在需要完成占比的计算逻辑。
表结构
users表
| user_id | created_at | sign_up_at | platform |
|---|---|---|---|
| 1 | 2021-01-01 00:01:01 | NULL | ios |
| 2 | 2021-01-10 07:13:42 | 2021-01-11 08:00:00 | web |
| 3 | 2021-02-01 12:11:44 | 2021-02-01 13:11:44 | android |
| 4 | 2021-02-28 04:32:12 | 2021-02-28 05:32:12 | ios |
| 5 | 2021-03-22 01:12:11 | 2021-03-22 02:12:11 | android |
offers表
| diagnosis_id | diagnosis_started_at | user_id |
|---|---|---|
| 1 | 2021-01-11 08:00:00 | 2 |
| 2 | 2021-02-01 13:11:44 | 3 |
| 3 | 2021-03-01 05:32:12 | 4 |
| 4 | 2021-03-21 02:12:11 | 10 |
| 5 | 2021-03-23 02:12:11 | 11 |
你已完成的查询
你已经写出的共同用户查询语句:
SELECT * FROM users a INNER JOIN offers b ON (a.user_id = b.user_id)
解决方案
方法1:子查询+COUNT直接计算
这是最直观的写法,分别统计符合条件的用户数和总用户数,再做除法得到比例:
SELECT ROUND((COUNT(DISTINCT a.user_id) / (SELECT COUNT(*) FROM users)) * 100, 2) AS user_percentage FROM users a INNER JOIN offers b ON a.user_id = b.user_id;
COUNT(DISTINCT a.user_id):确保同一个用户在offers表有多条记录时不重复计数(SELECT COUNT(*) FROM users):获取users表的总用户数ROUND(..., 2):将结果保留两位小数,让百分比更规整;如果不需要可以去掉
方法2:LEFT JOIN+SUM统计
如果不想用子查询,可以用左连接标记用户是否存在于offers表,再统计比例:
SELECT ROUND((SUM(CASE WHEN b.user_id IS NOT NULL THEN 1 ELSE 0 END) / COUNT(a.user_id)) * 100, 2) AS user_percentage FROM users a LEFT JOIN offers b ON a.user_id = b.user_id;
LEFT JOIN保留users表所有用户,不在offers表中的用户对应b.user_id为NULLSUM(CASE...)统计存在于offers表的用户数量COUNT(a.user_id)统计users表的总用户数
方法3:EXISTS子查询过滤统计
这种写法不需要连接表,直接检查每个用户是否在offers表中存在:
SELECT ROUND((COUNT(*) / (SELECT COUNT(*) FROM users)) * 100, 2) AS user_percentage FROM users a WHERE EXISTS (SELECT 1 FROM offers b WHERE b.user_id = a.user_id);
EXISTS会快速判断当前用户是否在offers表中有匹配记录,只返回符合条件的用户COUNT(*)统计这些用户的数量,再除以总用户数得到占比
内容的提问来源于stack exchange,提问作者smitkims
相关产品推荐
相关产品推荐

