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文档中带有递归的示例的查询与您最终使用的查询几乎相同。