You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用SQL将sales表数据转换为指定的月度销量交叉表格式?

嘿,这个需求属于典型的**行转列(Pivot)**场景,而且还要确保所有product和sales_man的组合都能显示(哪怕某个组合在特定月份没有销售数据)。我来给你拆解实现思路和具体代码:

核心思路

要达到目标输出,我们需要解决两个关键点:

  1. 生成所有product和sales_man的完整组合(避免遗漏那些没有销售记录的组合,比如产品02和销售经理xx的搭配)
  2. 将原数据按月份汇总销量,再通过条件判断把月份转为列,最后用0填充无数据的单元格

示例SQL代码(以MySQL为例)

-- 先生成所有产品和销售经理的唯一组合
WITH all_person_product AS (
    SELECT DISTINCT s1.product, s2.sales_man
    FROM sales s1
    CROSS JOIN sales s2
),
-- 按产品、销售经理、月份汇总销量
monthly_totals AS (
    SELECT 
        product,
        sales_man,
        -- 提取月份名称,MySQL用MONTHNAME,其他数据库需调整
        MONTHNAME(Date_s) AS month_name,
        SUM(qty) AS total_qty
    FROM sales
    GROUP BY product, sales_man, MONTHNAME(Date_s)
)
-- 左连接组合表,用CASE WHEN转列,无数据填0
SELECT 
    app.product,
    app.sales_man,
    COALESCE(MAX(CASE WHEN mt.month_name = 'January' THEN mt.total_qty END), 0) AS Jan,
    COALESCE(MAX(CASE WHEN mt.month_name = 'February' THEN mt.total_qty END), 0) AS Feb,
    COALESCE(MAX(CASE WHEN mt.month_name = 'March' THEN mt.total_qty END), 0) AS Mar
FROM all_person_product app
LEFT JOIN monthly_totals mt 
    ON app.product = mt.product 
    AND app.sales_man = mt.sales_man
GROUP BY app.product, app.sales_man
ORDER BY app.product, app.sales_man;

代码细节解释

  • all_person_product CTE:通过CROSS JOIN(笛卡尔积)生成所有产品和销售经理的组合,确保哪怕某个产品和销售经理没有交集记录,也会出现在结果里。
  • monthly_totals CTE:把原始销售数据按产品、销售经理、月份分组,计算每个分组的总销量。
  • 主查询:用CASE WHEN做条件聚合,把每个月份的销量转成单独的列;COALESCE函数用来把没有数据的NULL值替换成0,最后按产品和销售经理排序,让结果更规整。

适配其他数据库的调整

如果使用的不是MySQL,只需要调整提取月份名称的函数:

  • Oracle:把MONTHNAME(Date_s)换成TO_CHAR(Date_s, 'Mon')(注意月份缩写是大写,比如'JAN',对应CASE里的判断也要改成'JAN')
  • SQL Server:用DATENAME(MONTH, Date_s)获取月份名称
  • 老版本不支持CTE的数据库:可以把CTE替换成子查询形式

内容的提问来源于stack exchange,提问作者user8839166

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:20:47