SQL查询员工销售排名时姓名重复,如何实现单员工关联产品及总销售额展示
问题根因
你原SQL的CTE逻辑是按Emp_name(员工姓名)+Product_Name(产品名称)双维度分组,每款员工销售的产品都会生成独立行,且RANK()排序依据是单款产品的销售额,因此同一位员工销售多款产品时就会出现姓名重复展示的问题,排名规则也不符合“按员工总销售额取前15”的预期。
解决方案
根据你的需求提供两种常用实现方式,可根据实际使用的数据库类型选择:
方案1:单员工单行展示(聚合产品明细)
实现效果:每行对应一位员工,仅展示1次姓名,同时拼接所有销售产品明细、总销售笔数、总销售额,排名依据为员工总销售额取前15。
不同数据库的字符串聚合函数差异如下:
- MySQL:使用
GROUP_CONCAT - PostgreSQL/SQL Server:使用
STRING_AGG - Oracle:使用
LISTAGG
以下为通用逻辑示例(以MySQL为例,其他数据库替换聚合函数即可):
WITH emp_total AS ( -- 先按员工维度计算总销售额,取总销售额前15的员工 SELECT e.empid, e.Emp_name, COUNT(*) AS total_sales_count, SUM(s.sales_amount) AS total_sales_amount, RANK() OVER(ORDER BY SUM(s.sales_amount) DESC) AS rnk FROM sales_emp e INNER JOIN sales_sum1 s ON e.empid = s.empid GROUP BY e.empid, e.Emp_name ), emp_product AS ( -- 关联获取前15名员工的所有销售产品明细 SELECT et.Emp_name, GROUP_CONCAT(s.Product_Name SEPARATOR '、') AS product_list, et.total_sales_count, et.total_sales_amount FROM emp_total et INNER JOIN sales_sum1 s ON et.empid = s.empid WHERE et.rnk <= 15 GROUP BY et.Emp_name, et.total_sales_count, et.total_sales_amount ) SELECT * FROM emp_product;
方案2:明细+汇总层级展示
实现效果:保留各产品销售明细行,同时增加员工汇总行,员工姓名仅在首行展示1次,适合需要同时看明细和总金额的场景,使用ROLLUP实现分组汇总:
WITH emp_rank AS ( -- 先筛选出总销售额前15的员工 SELECT e.empid, e.Emp_name, RANK() OVER(ORDER BY SUM(s.sales_amount) DESC) AS rnk FROM sales_emp e INNER JOIN sales_sum1 s ON e.empid = s.empid GROUP BY e.empid, e.Emp_name ) SELECT CASE WHEN ROW_NUMBER() OVER(PARTITION BY er.Emp_name ORDER BY s.Product_Name) = 1 THEN er.Emp_name WHEN s.Product_Name IS NULL THEN '员工汇总' ELSE '' END AS Emp_name, IFNULL(s.Product_Name, '-') AS Product_Name, COUNT(*) AS sales_count, SUM(s.sales_amount) AS sales_amount FROM emp_rank er INNER JOIN sales_sum1 s ON er.empid = s.empid WHERE er.rnk <=15 GROUP BY er.Emp_name, s.Product_Name WITH ROLLUP ORDER BY er.Emp_name, s.Product_Name;
内容的提问来源于stack exchange,提问作者BABU
相关产品推荐
相关产品推荐

