You need to enable JavaScript to run this app. 如何编写SQL去除已完成/取消订单的其余无关状态行
优惠活动
大模型
产品
解决方案
定价
更多

如何编写SQL去除已完成/取消订单的其余无关状态行

解决方案

核心逻辑是先给不同订单状态设置业务优先级,终态(完成、取消)优先级高于所有中间状态和初始状态,每个订单仅保留优先级最高的一条状态记录即可。
首先明确已知的状态优先级规则:

  • 优先级1(最高):0485(订单完成),你可以把取消对应的状态码也补充到这一档
  • 优先级2:所有中间流转状态(比如示例里的0016、0028、0215等)
  • 优先级3(最低):0002(订单创建)

写法1:窗口函数实现(适配支持窗口函数的数据库,比如MySQL8.0+、PostgreSQL、SQL Server等)

这种写法逻辑清晰,执行效率也更高:

SELECT OrderNumber, OrderStatus
FROM (
    SELECT 
        A.OrderNumber, 
        C.OrderStatus,
        -- 按业务规则给状态打优先级,同一个订单里优先级数值越小排越靠前
        ROW_NUMBER() OVER (
            PARTITION BY A.OrderNumber 
            ORDER BY 
                CASE C.OrderStatus
                    WHEN '0485' THEN 1 -- 完成优先级最高,有取消状态也可以加一行 WHEN '取消状态码' THEN 1
                    WHEN '0002' THEN 3
                    ELSE 2 -- 其他中间状态统一归为第二优先级,不用逐个枚举
                END ASC
        ) AS rn
    FROM A 
    INNER JOIN B ON B.OrderNo = A.OrderNo 
    INNER JOIN C ON C.OrderStatus = B.OrderStat
) t
WHERE rn = 1; -- 每个订单只取优先级最高的1条记录

用你给的示例数据测试的话,最终输出结果就是订单180仅保留0485完成状态的记录,订单560没有终态,会保留全部三条状态记录,完全符合需求。


写法2:子查询实现(适配低版本不支持窗口函数的数据库,比如MySQL5.x)

如果你用的数据库不支持窗口函数,可以用这种写法,也可以直接套进你原来的SQL结构里:

SELECT A.OrderNumber, C.OrderStatus 
FROM A 
INNER JOIN B ON B.OrderNo = A.OrderNo 
INNER JOIN C ON C.OrderStatus = B.OrderStat
WHERE 
    -- 条件1:当前记录本身就是完成/取消的终态
    C.OrderStatus IN ('0485', '你的取消状态码')
    -- 条件2:当前订单本身就没有终态,保留所有状态记录
    OR A.OrderNumber NOT IN (
        SELECT DISTINCT B2.OrderNo
        FROM B B2
        INNER JOIN C C2 ON C2.OrderStatus = B2.OrderStat
        WHERE C2.OrderStatus IN ('0485', '你的取消状态码')
    );

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 23:33:00