无法找出此Postgresql递归自联接

时间:2019-07-25 08:02:41

标签: sql postgresql crosstab recursive-query self-join

嘿,我有下表:

+----+--------------+------------+----------+
| Id |     Name     |    Type    | ParentId |
+----+--------------+------------+----------+
|  1 | Team A       | team       | 2        |
|  2 | Initiative A | initiative | 3        |
|  3 | Initiative B | initiative | 4        |
|  4 | Initiative C | initiative | 5        |
|  5 | Product A    | product    | 6        |
|  6 | Product B    | product    | NULL     |
+----+--------------+------------+----------+

基本上,我想做的是递归自连接相同类型的父级,并且只保留相同类型的最高级别父级。 为了说明我的意思,如果我要在上表中执行递归联接,我期望得到以下结果:

+---------+--------+---------------+--------------+------------+-----------+
| Team_Id |  Team  | Initiative_Id |  Initiative  | Product_Id |  Product  |
+---------+--------+---------------+--------------+------------+-----------+
|       1 | Team A |             4 | Initiative C |          6 | Product B |
+---------+--------+---------------+--------------+------------+-----------+

我尝试通过WITH RECURSIVE CTE进行递归联接,但是我不知道如何在最终查询中“汇总”相同类型的父母。

3 个答案:

答案 0 :(得分:0)

以下内容将为您提供所需的项目列表-但您必须对它们进行转置才能获得具有多列的1行:

SELECT t1.* FROM table AS t1
LEFT JOIN table AS t2 ON t1.parentId = t2.id
WHERE t1.parentId IS NULL OR t1.type <> t2.type

答案 1 :(得分:0)

最好的方法是在json中生成这些列,您可以尝试将json转换为报表。

但是,您可以使用json_to_record(),但需要预定义的列类型。

with cte as (
      SELECT
        '{' || translate( 
            (translate((json_agg
                (json_build_object(type || 'id', id, type || 'name', name)))::text, '[]', '')),
           '{}', '') || '}' as name          
      FROM table1 
      WHERE id in (
        select max(id) from table1 group by type)
)
select x.* FROM cte
cross join json_to_record(cte.name::json) AS x(teamid text, teamname text, initiativeid text, initiativename text, productid text, productname text);

答案 2 :(得分:0)

我认为我可以通过以下递归CTE解决它。我可以从该查询的结果中看到同类型的最高父。

WITH RECURSIVE parent_rollup AS (
  SELECT
        -1,
        -1,
        NULL,
        NULL AS rolled_up_parent_group_uuid,
        NULL AS rolled_up_type
    FROM table t

  UNION

  SELECT
         t.Id,
         t.ParentId,
         t.type,
         t2.Id,
         t2.Type
    FROM table t
    LEFT JOIN table t1
      ON t.ParentId = t.Id
    JOIN parent_rollup t2
      ON t1.ParentId = t2.Id
)