【问题标题】:PostgreSQL WITH RECURSIVE query to get ordered parent-child chain by a Partition KeyPostgreSQL WITH RECURSIVE 查询通过分区键获取有序的父子链
【发布时间】:2019-03-02 06:14:39
【问题描述】:

我在 PostgreSQL 9.6.6 上编写 sql 脚本时遇到问题,该脚本通过使用步骤的父子 ID 对进程中的步骤进行排序,并且每个进程 ID 都进行了分组/分区。我在这里找不到这种特殊情况,因此如果我错过了它,我深表歉意,并请您提供 cmets 中解决方案的链接。

案例:我有一张如下所示的表格:

processID | stepID | parentID
     1         1          NULL
     1         3           5
     1         2           4
     1         4           3
     1         5           1
     2         1          NULL
     2         3           5
     2         2           4
     2         4           3
     2         5           1

现在我必须从每个 processID 的 parentID 为 NULL 的步骤开始对步骤进行排序。

注意:我不能简单地订购 StepID 或 parentID,因为我在整个流程中放置的新步骤会获得比流程中的最后一步更高的 stepID(连续生成代理键)。

我必须为每个 processID 订购步骤,我将收到以下输出:

processID | stepID | parentID
     1         1          NULL
     1         5           1
     1         3           5
     1         4           3
     1         2           4
     2         1          NULL
     2         5           1
     2         3           5
     2         4           3
     2         2           4

我试图用 CTE 函数 WITH RECURSIVE 来做到这一点:

    WITH RECURSIVE
starting (processID,stepID, parentID) AS
  (
    SELECT b.processID,b.stepID, b.parentID
    FROM process b
    WHERE b.parentID ISNULL
  ),
  descendants (processID,stepID, parentID) AS
  (
    SELECT b.processID,b.stepID, b.stepparentID
    FROM starting b
    UNION ALL
    SELECT b.processID,b.stepID, b.parentID
    FROM process b

    JOIN descendants AS c ON b.parentID = c.stepID
)
SELECT * FROM descendants

结果不是我要寻找的。由于我们有数百个进程,我收到一个列表,其中第一条记录是不同的 processID,它们的 parentID 为 NULL。

我想我必须再次在 processID 上递归整个脚本,但不知道如何。

感谢您的帮助!

【问题讨论】:

    标签: postgresql common-table-expression window-functions recursive-query with-statement


    【解决方案1】:

    你应该计算每一步的水平:

    with recursive starting as (
        select processid, stepid, parentid, 0 as level
        from process
        where parentid is null
    union all
        select p.processid, p.stepid, p.parentid, level+ 1
        from starting s
        join process p on s.stepid = p.parentid and s.processid = p.processid
    )
    select *
    from starting
    order by processid, level
    
     processid | stepid | parentid | level 
    -----------+--------+----------+-------
             1 |      1 |          |     0
             1 |      5 |        1 |     1
             1 |      3 |        5 |     2
             1 |      4 |        3 |     3
             1 |      2 |        4 |     4
             2 |      1 |          |     0
             2 |      5 |        1 |     1
             2 |      3 |        5 |     2
             2 |      4 |        3 |     3
             2 |      2 |        4 |     4
    (10 rows)   
    

    当然,如果不需要,可以跳过最终选择中的最后一列。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-01
      • 2019-12-20
      • 2019-08-29
      • 1970-01-01
      • 2014-03-17
      相关资源
      最近更新 更多