如何从Orders表统计订单数与对应用户数的频率分布?
生成订单数-用户数频率分布的SQL方案
嘿,这个需求拆两步就能轻松实现,我来给你详细拆解:
首先得明确一个关键前提:如果要统计订单数为0的用户(就像示例里的2000个用户),你必须有一张存储所有用户信息的Users表(主键是id,和Orders表的user_id关联)。如果只有Orders表,那只能统计有过下单记录的用户分布,没法获取从未下单的用户数据。
情况1:有独立的Users表(支持统计0订单用户)
这是最常见的业务场景,我们可以通过左连接全量用户和订单数据,先算出每个用户的订单数,再对订单数分组统计用户量:
SELECT order_count AS 订单数, COUNT(user_id) AS 用户数 FROM ( -- 子查询:统计每个用户的订单数量(无订单的用户会返回0) SELECT u.id AS user_id, COUNT(o.id) AS order_count FROM Users u LEFT JOIN Orders o ON u.id = o.user_id -- 可选:过滤无效订单(比如已取消/退款的,根据你的status枚举值调整) -- WHERE o.status IS NULL OR o.status NOT IN (2, 3) -- 假设2、3是取消/无效状态 GROUP BY u.id ) AS user_order_counts GROUP BY order_count ORDER BY order_count ASC;
代码说明:
- 子查询用
LEFT JOIN确保所有用户都被纳入统计,没有订单的用户COUNT(o.id)会返回0; - 外层查询按
order_count分组,统计每个订单数对应的用户数量,最后按订单数升序排列,和你给出的示例格式完全匹配; - 如果需要排除特定状态的订单(比如已取消的),可以在子查询里添加
WHERE条件,注意要保留o.status IS NULL(对应无订单的用户)。
情况2:只有Orders表(仅统计有订单的用户)
如果没有全量用户表,那只能统计有过下单记录的用户的订单分布:
SELECT order_count AS 订单数, COUNT(user_id) AS 用户数 FROM ( -- 子查询:统计每个下单用户的订单数量 SELECT user_id, COUNT(id) AS order_count FROM Orders -- 可选:过滤无效订单 -- WHERE status NOT IN (2, 3) GROUP BY user_id ) AS user_order_counts GROUP BY order_count ORDER BY order_count ASC;
补充提示:
如果你的status枚举有不同业务含义(比如1=已完成,2=已取消),记得根据需求过滤订单,确保统计的是符合业务逻辑的有效订单数量。
内容的提问来源于stack exchange,提问作者Amin Shah Gilani




