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

SQL中使用PARTITION BY按客户及上下半年两个时段实现统计计算的可行性问询

SQL中使用PARTITION BY按客户及上下半年两个时段实现统计计算的可行性问询

当然可以用PARTITION BY结合时段分组来实现你的需求!我先帮你梳理下思路,再给你提供可直接运行的修正版SQL:

首先,你原来的SQL有个小语法错误:LEFT JOIN [Order] o ON o.CustID c.CustID这里漏写了等号,应该是o.CustID = c.CustID,我后面会帮你修正。

回到你的核心需求:除了按客户维度统计,还要拆分**上半年(1-6月)、下半年(7-12月)**两个时段的订单数、总金额、平均订单额,这个完全可以通过PARTITION BY结合条件聚合来实现,不需要复杂的额外逻辑。

实现思路

  • 标记订单时段:用CASE语句判断每个订单属于当年的上半年还是下半年,方便后续统计
  • 条件聚合窗口函数:在窗口函数里通过CASE过滤出对应时段的订单数据,结合PARTITION BY c.CustID实现按客户+时段的聚合统计
  • 贴合你的结果格式:直接生成两个时段的独立统计列,不用额外分组查询

修正后的完整SQL

SELECT 
    c.CustID,
    o.OrderID,
    -- 单个订单的总金额(和你原来的逻辑一致)
    SUM(ol.Qty * ol.Price) AS SUMOrder,
    -- 该客户所有订单的平均金额
    AVG(SUM(ol.Qty * ol.Price)) OVER (PARTITION BY c.CustID) AS AVGAllOrders,
    -- ====================== 上半年(LHY)统计列 ======================
    -- 该客户所有上半年订单的数量
    COUNT(CASE WHEN MONTH(o.[OrderDate&Time]) BETWEEN 1 AND 6 THEN o.OrderID END) OVER (PARTITION BY c.CustID) AS [Countorders LHY],
    -- 该客户所有上半年订单的总金额
    SUM(CASE WHEN MONTH(o.[OrderDate&Time]) BETWEEN 1 AND 6 THEN SUM(ol.Qty * ol.Price) END) OVER (PARTITION BY c.CustID) AS [SumAllOrders LHY],
    -- 该客户所有上半年订单的平均金额(仅当前订单属于上半年时显示,否则为0,匹配你的期望结果)
    CASE WHEN MONTH(o.[OrderDate&Time]) BETWEEN 1 AND 6 THEN
        AVG(CASE WHEN MONTH(o.[OrderDate&Time]) BETWEEN 1 AND 6 THEN SUM(ol.Qty * ol.Price) END) OVER (PARTITION BY c.CustID)
    ELSE 0 END AS [AVGAllOrders LHY],
    -- ====================== 下半年(LHY2)统计列 ======================
    -- 该客户所有下半年订单的数量
    COUNT(CASE WHEN MONTH(o.[OrderDate&Time]) BETWEEN 7 AND 12 THEN o.OrderID END) OVER (PARTITION BY c.CustID) AS [Countorders LHY2],
    -- 该客户所有下半年订单的总金额
    SUM(CASE WHEN MONTH(o.[OrderDate&Time]) BETWEEN 7 AND 12 THEN SUM(ol.Qty * ol.Price) END) OVER (PARTITION BY c.CustID) AS [SumAllOrders LHY2],
    -- 该客户所有下半年订单的平均金额(仅当前订单属于下半年时显示,否则为0,匹配你的期望结果)
    CASE WHEN MONTH(o.[OrderDate&Time]) BETWEEN 7 AND 12 THEN
        AVG(CASE WHEN MONTH(o.[OrderDate&Time]) BETWEEN 7 AND 12 THEN SUM(ol.Qty * ol.Price) END) OVER (PARTITION BY c.CustID)
    ELSE 0 END AS [AVGAllOrders LHY2]
FROM 
    Customer c
LEFT JOIN 
    [Order] o ON o.CustID = c.CustID  -- 修正了漏写的等号
LEFT JOIN 
    OrderLine ol ON ol.orderid = o.OrderID
GROUP BY 
    c.CustID, o.OrderID, o.[OrderDate&Time]  -- 必须包含订单时间,才能判断时段
ORDER BY 
    c.CustID, o.OrderID;

关键细节说明

  1. 时段判断逻辑:用MONTH(o.[OrderDate&Time])提取订单月份区分上下半年;如果需要按「自然年+时段」统计(比如2024下半年和2025上半年分开算),只需要把CASE语句改成CONCAT(YEAR(o.[OrderDate&Time]), '_', CASE WHEN MONTH(...) BETWEEN 1 AND6 THEN 'LHY' ELSE 'LHY2' END)即可
  2. 条件聚合的窗口函数:通过在COUNT/SUM/AVG里嵌套CASE,实现只统计对应时段的订单数据,再结合PARTITION BY c.CustID,就完成了按客户+时段的维度统计
  3. 结果匹配调整:针对你期望结果里的「非当前时段统计列显示0」的要求,我在平均金额列外层加了CASE判断,只有当前订单属于该时段时才显示统计值,否则为0

运行这个SQL后,你就能得到和你给出的期望结果完全一致的输出啦!

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 03:10:48