如何按规则将TOP3值转为3列?求各客户各销售月TOP3卖家SQL方案
解决方案:获取每个客户每月金额TOP3商品并转为多列
嘿,你已经迈出了关键的第一步——拿到了每个分组的第一名!要实现每个客户各销售月份金额前三的商品并转为3列的需求,我们可以通过「先筛选TOP3数据,再条件聚合转列」的思路来完成,下面是具体的SQL方案:
步骤1:获取带排名的TOP3数据集
首先我们需要给每个客户每个月的商品按金额降序排名,筛选出排名前3的记录。你用的DENSE_RANK()用法没问题,但要注意:如果有多个商品金额相同,DENSE_RANK()会给它们相同的排名(比如两个商品都是第二,下一个就是第三);如果希望即使金额相同也强制生成唯一排名,可以改用ROW_NUMBER()。
先写出带排名的子查询:
SELECT MONTH(Sales_Date) AS Sales_month, Customer_ID, Item, Amount, DENSE_RANK() OVER ( PARTITION BY MONTH(Sales_Date), Customer_ID ORDER BY Amount DESC ) AS item_rank FROM q2
这个查询会给每个Sales_month + Customer_ID分组下的商品按金额从高到低排名,我们后续只需要保留item_rank <= 3的记录。
步骤2:条件聚合将TOP3转为多列
接下来我们用条件聚合函数(比如MAX()配合CASE WHEN),把每个分组下不同排名的商品分别放到对应的列中。如果需要同时展示金额,也可以一起转换:
完整SQL代码
SELECT Sales_month, Customer_ID, -- 获取排名第1的商品和金额 MAX(CASE WHEN item_rank = 1 THEN Item END) AS Top1_Item, MAX(CASE WHEN item_rank = 1 THEN Amount END) AS Top1_Amount, -- 获取排名第2的商品和金额 MAX(CASE WHEN item_rank = 2 THEN Item END) AS Top2_Item, MAX(CASE WHEN item_rank = 2 THEN Amount END) AS Top2_Amount, -- 获取排名第3的商品和金额 MAX(CASE WHEN item_rank = 3 THEN Item END) AS Top3_Item, MAX(CASE WHEN item_rank = 3 THEN Amount END) AS Top3_Amount FROM ( SELECT MONTH(Sales_Date) AS Sales_month, Customer_ID, Item, Amount, DENSE_RANK() OVER ( PARTITION BY MONTH(Sales_Date), Customer_ID ORDER BY Amount DESC ) AS item_rank FROM q2 ) AS ranked_items WHERE item_rank <= 3 GROUP BY Sales_month, Customer_ID ORDER BY Sales_month, Customer_ID;
结果说明
用你提供的样本数据运行这个SQL,会得到类似这样的结果:
| Sales_month | Customer_ID | Top1_Item | Top1_Amount | Top2_Item | Top2_Amount | Top3_Item | Top3_Amount |
|---|---|---|---|---|---|---|---|
| 7 | CCC | Nike | 1000 | NULL | NULL | NULL | NULL |
| 8 | AAA | Apple | 5600 | Kindle | 900 | Pear | 600 |
| 8 | BBB | Cola | 20 | NULL | NULL | NULL | NULL |
| 9 | BBB | LEGO | 240 | NULL | NULL | NULL | NULL |
| 9 | CCC | Kindle | 5000 | Apple | 2500 | Nike | 1000 |
如果某个客户当月的商品不足3个,对应的列会显示NULL,这符合实际业务场景。
小提示
- 如果你使用的是支持
PIVOT语法的数据库(比如SQL Server、Oracle),也可以用PIVOT来实现转列,但CASE WHEN的写法兼容性更强,在MySQL、PostgreSQL等数据库都能运行。 - 若要避免
NULL,可以用COALESCE()函数替换MAX(),把NULL替换成你需要的默认值(比如''或'无')。
内容的提问来源于stack exchange,提问作者Jerry Lin
相关产品推荐
相关产品推荐

