【问题标题】:RECURSIVE query for Postgres on a single table在单个表上对 Postgres 进行递归查询
【发布时间】:2020-04-08 14:04:10
【问题描述】:

我想在 Postgres 中的单个表上创建一个 RECURSIVE 查询,它基本上是基于父和子的。

这是带有数据的演示表员工

id     parentid   managerid   status
------------------------------------
3741    [null]      1709        7    
3742     3741       1709        12    
3749     3742       1709        12    
3900     3749       1709        4

1) 如果 Status = 12 那么结果将是具有 status = 12 的数据以及该特定的所有 父母节点。

预期结果将是:

 id     parentid   managerid   status
--------------------------------------
 3741   [null]      1709        7    
 3742    3741       1709        12    
 3749    3742       1709        12    

为此,我已经尝试过下面给出的查询工作正常并给出正确的结果,即使我更改了状态值而不是它的工作正常。

WITH RECURSIVE nodes AS (
      SELECT s1.id, case when s1.parentid=s1.id then null else s1.parentid end parentid,s1.managerid, s1.status
        FROM employees s1 WHERE id IN 
        (SELECT employees.id  FROM employees WHERE 
              "employees"."status" = 12 AND "employees"."managerid" = 1709)
      UNION ALL
      SELECT s2.id, case when s2.parentid=s2.id then null else s2.parentid end parentid,s2.managerid, s2.status
        FROM employees s2 JOIN nodes ON s2.id = nodes.parentid
)
SELECT distinct nodes.id, nodes.parentid, nodes.managerid, nodes.status  
      FROM nodes ORDER BY nodes.id ASC NULLS FIRST;

2) 如果 Status != 12 那么结果将是,只有该特定节点的所有 父母

预期结果将是:

 id     parentid   managerid   status
--------------------------------------
 3741   [null]      1709        7    

我希望查询状态不等于某个值。

【问题讨论】:

    标签: postgresql recursive-query


    【解决方案1】:
    WITH RECURSIVE cte AS (
      SELECT * FROM tablename
      WHERE status != 12
      UNION
      SELECT t.* 
      FROM tablename t INNER JOIN cte c
      ON c.parentid = t.id
    )
    SELECT DISTINCT * FROM cte;
    

    更多请参考演示:demo

    【讨论】:

      【解决方案2】:

      这是一个非常简单的解决方案,但我认为它应该适用于较小的数据集

        SELECT * FROM employee
        WHERE 
          status=12
          OR id IN (
            SELECT DISTINCT parentId FROM employee WHERE status=12
          )
      `
      

      【讨论】:

      • 它不起作用,因为状态值可能会有所不同。您的查询给出的结果仅适用于状态 = 12,即使我在查询中保留状态 = 4,它也无法正常工作。
      • 我实际上在查询中使用了两次相同的状态。请确认两者每次都更新
      • 是的,我在这两个地方都进行了更新。如需更多信息,请参阅link。我们需要这样的工作流程。在此链接中提供了演示,我们希望过滤特定列,如链接所示。我实际上需要查询在演示中应用的列上应用过滤器..
      【解决方案3】:

      使用此递归 CTE:

      with recursive cte as (
        select * from tablename
        where status = 12
        union all
        select t.* 
        from tablename t inner join cte c
        on c.parentid = t.id
      )
      select distinct * from cte;
      

      请参阅demo
      结果:

      | id   | parentid | managerid | status |
      | ---- | -------- | --------- | ------ |
      | 3741 |          | 1709      | 7      |
      | 3742 | 3741     | 1709      | 12     |
      | 3749 | 3742     | 1709      | 12     |
      

      【讨论】:

      【解决方案4】:
      WITH RECURSIVE CTE AS
      (
       SELECT *
       FROM tablename
       WHERE status = 12
       UNION
       SELECT t.*
       FROM tablename t
       INNER JOIN cte c ON c.Id = t.parentid
      )
      SELECT t.*
      FROM tablename t
      LEFT JOIN cte c on t.id=c.id
      WHERE c.id IS NULL
      ORDER BY id ASC NULLS FIRST;
      

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-15
      • 2014-10-29
      • 2011-05-17
      • 1970-01-01
      相关资源
      最近更新 更多