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

SQL如何按条件从各分区中获取符合关联规则的最新记录集

按分类获取最新关联记录组的SQL实现

问题背景

现有业务表结构如下:

idstatusdatecategory
1PENDING2022-07-01XYZ
2DONE2022-07-04XYZ
3PENDING2022-07-03DEF
4DONE2022-07-08DEF

基础需求为取每个category下最新的记录,示例预期返回id=2、4的记录。实际业务需适配两个特殊场景:

  • 同一分类下记录以链路成对形式存在,可能超过2条:例如下表中XYZ分类共4条记录,DEF分类共2条记录,预期返回id=3、4、6的记录;如果某分类下共6条3代关联记录,需返回最新一代的3条记录。
    idstatusdatecategory
    1PENDING2022-07-01XYZ
    2PENDING2022-07-02XYZ
    3FAILED2022-07-04XYZ
    4FAILED2022-07-05XYZ
    5PENDING2022-07-03DEF
    6DONE2022-07-08DEF
  • 同一分类下最新批次的记录date字段可能相同,不能仅靠日期排序取单条。

此前尝试的dense_rank()按日期排序取排名1的方案,仅能返回同日期的顶层记录,无法覆盖多代链路的批量返回需求。

补充字段信息

表中存在prev_id字段标识记录的关联关系,完整表结构如下:

idstatusdatecategoryprev_id
1PENDING2022-07-01XYZ{}
2PENDING2022-07-02XYZ{}
3FAILED2022-07-04XYZ{1}
4FAILED2022-07-05XYZ{2}
5PENDING2022-07-03DEF{}
6DONE2022-07-08DEF{5}

prev_id值为{}代表是链路起始节点,非空值存储当前记录直接关联的上一级记录id。

实现方案

核心思路是先遍历每个分类下的关联链路,给不同代际的记录打标,最终返回每个分类下最新代际的所有记录即可,支持递归的数据库(PostgreSQL、MySQL 8.0+、SQL Server等)可直接使用如下SQL:

WITH RECURSIVE link_trace AS (
    -- 锚点:查询所有链路起始节点,标记代际为1
    SELECT
        id,
        status,
        `date`,
        category,
        prev_id,
        1 AS gen
    FROM tbl
    WHERE prev_id = '{}'

    UNION ALL

    -- 递归关联下一级节点,代际累加
    SELECT
        t.id,
        t.status,
        t.`date`,
        t.category,
        t.prev_id,
        lt.gen + 1 AS gen
    FROM tbl t
    JOIN link_trace lt
        ON t.category = lt.category
        AND CAST(TRIM('{}' FROM t.prev_id) AS UNSIGNED) = lt.id
),
max_gen_per_cat AS (
    -- 计算每个分类的最大代际(最新批次)
    SELECT
        category,
        MAX(gen) AS latest_gen
    FROM link_trace
    GROUP BY category
)
-- 关联返回最新批次的所有记录
SELECT lt.id, lt.status, lt.`date`, lt.category, lt.prev_id
FROM link_trace lt
JOIN max_gen_per_cat mg
    ON lt.category = mg.category
    AND lt.gen = mg.latest_gen
ORDER BY lt.id;

逻辑说明

  • 递归CTE会自动遍历每个分类下的全量关联链路,从起始节点开始逐层向下匹配,给每层节点分配代际编号,不存在漏匹配问题
  • 聚合得到每个分类的最大代际值后,筛选出所有属于该代际的记录,自动适配同日期、多记录、不同链路长度的场景
  • 针对给出的示例数据,执行后返回id=3、4、6的记录,完全符合预期;如果分类下存在3代共6条关联记录,会自动返回第三代的全部3条记录。

如果使用不支持递归CTE的数据库版本,可以通过prev_id的关联深度计算代际:例如prev_id为空是第1代,指向第1代的是第2代,指向第2代的是第3代,通过多轮关联打标即可实现相同效果。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 19:01:46