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

Oracle SQL如何查询曾经过指定前置状态的目标状态ID记录

Oracle SQL 筛选满足状态先后顺序要求的记录

核心逻辑

要实现「目标状态为d时,必须在d之前的流转中出现过前置状态b,先d后b的场景不满足要求」的筛选,核心判断依据是同一个ID下,前置状态b的变更时间必须早于目标状态d的变更时间。
前提:你的状态流转表需包含3个核心字段:

  • id:业务记录唯一标识
  • status:状态值
  • operate_time:状态变更时间(如果没有时间字段,用自增的流转记录ID替代,数值越大代表记录越新即可)

实现代码

写法1:EXISTS关联(可读性高,性能好)

直接判断是否存在早于当前d状态的b状态记录即可:

SELECT 
    t.id,
    t.status
FROM 你的状态流转表名 t
WHERE t.status = 'd' -- 筛选目标状态为d的记录
AND EXISTS (
    SELECT 1
    FROM 你的状态流转表名 pre
    WHERE pre.id = t.id
      AND pre.status = 'b' -- 匹配指定前置状态b
      AND pre.operate_time < t.operate_time -- 保证b的出现时间早于d,排除反向顺序场景
)

如果需要额外排除「出现d之后又回退到b」的场景,追加如下条件即可:

AND NOT EXISTS (
    SELECT 1
    FROM 你的状态流转表名 after_t
    WHERE after_t.id = t.id
      AND after_t.status = 'b'
      AND after_t.operate_time > t.operate_time
)

写法2:窗口函数(适合批量校验多组状态规则)

如果需要同时校验多组前置-目标状态,用窗口函数一次性计算每个ID下各状态的首次出现时间再做判断更高效:

WITH status_calc AS (
    SELECT 
        id,
        status,
        operate_time,
        -- 计算每个ID下b状态首次出现的时间
        MIN(CASE WHEN status = 'b' THEN operate_time END) OVER (PARTITION BY id) AS first_b_time,
        -- 计算每个ID下d状态首次出现的时间
        MIN(CASE WHEN status = 'd' THEN operate_time END) OVER (PARTITION BY id) AS first_d_time
    FROM 你的状态流转表名
)
SELECT DISTINCT id, status
FROM status_calc
WHERE status = 'd'
  AND first_b_time IS NOT NULL -- 历史上存在b状态
  AND first_b_time < first_d_time -- b首次出现时间早于d首次出现时间

示例参考

状态流转规则示例

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 06:17:02