Sql 用于展平树的简单通用表表达式

Sql 用于展平树的简单通用表表达式,sql,postgresql,common-table-expression,Sql,Postgresql,Common Table Expression,以下是我的表格格式。 表名::用户 userid reporttouserid ------ ------------ 101 NULL 102 101 103 102 现在我需要一个查询来列出101下的所有子用户ID,即102和103(103间接地在101下,因为它的父用户102在101下) 我已经在postgresql中看到了常用的表表达式,但还没有弄清楚如何使用它。介绍了这个主题。请参见该页上给出的递归CTE示例 递归CTE可能有点难以理解,但一旦使用它们,它就会非常强

以下是我的表格格式。 表名::用户

userid reporttouserid
------ ------------
101    NULL
102    101
103    102
现在我需要一个查询来列出101下的所有子用户ID,即102和103(103间接地在101下,因为它的父用户102在101下)

我已经在postgresql中看到了常用的表表达式,但还没有弄清楚如何使用它。

介绍了这个主题。请参见该页上给出的递归CTE示例

递归CTE可能有点难以理解,但一旦使用它们,它就会非常强大。阅读一些文档和实验;你会明白的

(请始终提及您的PostgreSQL版本,并在问题中以表格形式显示所需的输出)

给定演示数据:

create table users (
  userid integer primary key,
  reporttouserid integer references users(userid)
);

insert into users(userid, reporttouserid) values (101,null), (102,101), (103,102);
(请尽可能在问题中提供此信息,创建此信息是一种痛苦)

您可以使用以下方法递归遍历图形:

WITH RECURSIVE flatusers(userid, reporttouserid, baseuserid) AS (
    SELECT userid, reporttouserid, userid AS baseuserid 
    FROM users WHERE reporttouserid IS NULL
    UNION ALL
    SELECT u.userid, u.reporttouserid, f.baseuserid
    FROM flatusers f
    INNER JOIN users u ON f.userid = u.reporttouserid

)
SELECT * FROM flatusers;
产生如下产出:

 userid | reporttouserid | baseuserid 
--------+----------------+------------
    101 |                |        101
    102 |            101 |        101
    103 |            102 |        101
(3 rows)
我相信你能想出从那以后的路。在使用递归CTE之前,请确保您理解该CTE

请注意,PostgreSQL(至少9.4或更早版本)无法(不幸地)将quals下推到CTE术语中,即使对于非递归CTE也是如此。如果将
WHERE baseuserid=101
添加到查询中,查询仍将生成整个展平表,然后丢弃大部分。如果只想对一个baseuserid执行此递归操作,则必须在递归CTE术语的静态联合部分中的
WHERE reporttouserid为NULL
之后添加相应的
WHERE
子句术语。

包含此主题。请参见该页上给出的递归CTE示例

递归CTE可能有点难以理解,但一旦使用它们,它就会非常强大。阅读一些文档和实验;你会明白的

(请始终提及您的PostgreSQL版本,并在问题中以表格形式显示所需的输出)

给定演示数据:

create table users (
  userid integer primary key,
  reporttouserid integer references users(userid)
);

insert into users(userid, reporttouserid) values (101,null), (102,101), (103,102);
(请尽可能在问题中提供此信息,创建此信息是一种痛苦)

您可以使用以下方法递归遍历图形:

WITH RECURSIVE flatusers(userid, reporttouserid, baseuserid) AS (
    SELECT userid, reporttouserid, userid AS baseuserid 
    FROM users WHERE reporttouserid IS NULL
    UNION ALL
    SELECT u.userid, u.reporttouserid, f.baseuserid
    FROM flatusers f
    INNER JOIN users u ON f.userid = u.reporttouserid

)
SELECT * FROM flatusers;
产生如下产出:

 userid | reporttouserid | baseuserid 
--------+----------------+------------
    101 |                |        101
    102 |            101 |        101
    103 |            102 |        101
(3 rows)
我相信你能想出从那以后的路。在使用递归CTE之前,请确保您理解该CTE


请注意,PostgreSQL(至少9.4或更早版本)无法(不幸地)将quals下推到CTE术语中,即使对于非递归CTE也是如此。如果将
WHERE baseuserid=101
添加到查询中,查询仍将生成整个展平表,然后丢弃大部分。如果您只想对一个baseuserid执行此递归操作,则必须在递归CTE术语的静态联合部分中的
WHERE reporttouserid为NULL
之后添加相应的
WHERE
子句术语。

请显示您尝试了什么,到目前为止,我所做的是通过加入userid来选择直接子级,并将其传递给java后端中的递归函数以查找后续用户。我更愿意在sql本身中这样做。我无法理解如何用sql编写这种递归查询。感谢memory Services,PG文档中的with recursive示例有一个与您最终使用的查询几乎相同的查询。请说明您尝试了什么,以及为什么它不适用于您。到目前为止,我所做的是通过加入userid来选择直接子项,并将其传递到java后端中的递归函数以查找后续用户。我更愿意在sql本身中这样做。我无法理解如何用sql编写这种递归查询。谢天谢地,如果内存可用,PG文档中带有递归的示例的查询与您最终使用的查询几乎相同。