SQL查询问题:如何获取客户ID、姓名及对应下单次数最多的餐品类别

原SQL存在的问题
- 逻辑不符合需求:原SQL的作用是筛选出所有客户中总下单次数最多的客户,和「统计每个客户各自下单次数最多的餐品类别」的需求完全不匹配
- 分组逻辑错误:要统计每个客户不同餐品类别的下单次数,需要同时按
Customer_ID、F_Catg两个维度分组,原SQL仅按Customer_ID分组,无法得到不同餐品类别的单独统计值 - 缺少要求返回的字段:原查询结果只有客户ID、总统计数,缺少需求要求的客户姓名、对应最高频餐品类别两个关键字段
- 未覆盖并列场景:如果某个客户有多个餐品类别下单次数并列最高,原逻辑也无法识别这类情况
修复方案
推荐使用窗口函数实现,兼容MySQL 8.0+、PostgreSQL、SQL Server等所有主流新版数据库:
WITH customer_catg_count AS ( -- 先统计每个客户每个餐品类别的下单次数 SELECT ORD.Customer_ID, ORD.Customer_Name, -- 若客户姓名存储在单独的客户表,关联对应表取字段即可 FM.F_Catg, COUNT(*) AS order_cnt FROM ORDER_RECORD ORD INNER JOIN FOOD_MENU FM ON ORD.Item_ID = FM.Item_ID GROUP BY ORD.Customer_ID, ORD.Customer_Name, FM.F_Catg ), rank_result AS ( -- 按客户分组,给每个客户的餐品类别的下单次数做排名 SELECT *, RANK() OVER(PARTITION BY Customer_ID ORDER BY order_cnt DESC) AS rk FROM customer_catg_count ) -- 取每个客户排名第一的记录,即为下单次数最多的餐品类别,并列第一也会同时返回 SELECT Customer_ID, Customer_Name, F_Catg AS most_ordered_catg FROM rank_result WHERE rk = 1;
如果是不支持窗口函数的旧版本MySQL,可以用关联子查询实现:
SELECT t1.Customer_ID, t1.Customer_Name, t1.F_Catg AS most_ordered_catg FROM ( SELECT ORD.Customer_ID, ORD.Customer_Name, FM.F_Catg, COUNT(*) AS order_cnt FROM ORDER_RECORD ORD INNER JOIN FOOD_MENU FM ON ORD.Item_ID = FM.Item_ID GROUP BY ORD.Customer_ID, ORD.Customer_Name, FM.F_Catg ) t1 WHERE t1.order_cnt = ( SELECT MAX(order_cnt) FROM ( SELECT ORD.Customer_ID, COUNT(*) AS order_cnt FROM ORDER_RECORD ORD INNER JOIN FOOD_MENU FM ON ORD.Item_ID = FM.Item_ID GROUP BY ORD.Customer_ID, FM.F_Catg ) t2 WHERE t2.Customer_ID = t1.Customer_ID )
内容的提问来源于stack exchange,提问作者513dgehammer
相关产品推荐
相关产品推荐

