下面两个表为我提供了每个用户拥有的文件路径:

create temp table object as (
  select 1 id, 'MyFile1' name union all
  select 2 id, 'MyFile2' name union all
  select 3 id, 'MyFolder' name union all
  select 4 id, 'SomeFile' name union all
  select 5 id, 'Hello' name
);
create temp table path as (
  select 1 user_id, 1 object_id, NULL parent_folder union all
  select 1 user_id, 2 object_id, NULL parent_folder union all
  select 1 user_id, 3 object_id, NULL parent_folder union all
  select 1 user_id, 4 object_id, 3 parent_folder union all
  select 2 user_id, 5 object_id, NULL parent_folder union all
  select 2 user_id, 1 object_id, NULL parent_folder
);

例如,对于用户1,其目录 struct 如下所示:

MyFile1
MyFile2
MyFolder/
    SomeFile

我正在try 构建一个递归CTE,这样它就可以显示用户及其路径.以下是查询应该返回的内容:

user_id           path
1                 MyFile1
1                 MyFile2
1                 MyFolder
1                 MyFolder/SomeFile
2                 Hello
2                 MyFile1

我目前有以下正在工作的查询,但想知道是否有可能在可读性或性能方面进行改进:

create temp table object as (
  select 1 id, 'MyFile1' name union all
  select 2 id, 'MyFile2' name union all
  select 3 id, 'MyFolder' name union all
  select 4 id, 'SomeFile' name union all
  select 5 id, 'Hello' name
);

create temp table path as (
  select 1 user_id, 1 object_id, NULL parent_folder union all
  select 1 user_id, 2 object_id, NULL parent_folder union all
  select 1 user_id, 3 object_id, NULL parent_folder union all
  select 1 user_id, 4 object_id, 3 parent_folder union all
  select 2 user_id, 5 object_id, NULL parent_folder union all
  select 2 user_id, 1 object_id, NULL parent_folder
);

WITH RECURSIVE all_paths AS (
    SELECT user_id, id, name AS path FROM path JOIN object ON path.object_id=object.id WHERE parent_folder IS NULL
    UNION ALL
    SELECT all_paths.user_id, null, CONCAT(all_paths.path, '/', object.name) 
    FROM all_paths JOIN path ON all_paths.id = path.parent_folder join object ON path.object_id=object.id
) SELECT * FROM all_paths ORDER BY user_id, path

enter image description here

推荐答案

你 Select 的方法是有效的,也是好的.递归联接部分中还有另一个联接.这确实会使查询不容易阅读.一种好的做法是在递归联接之前或之后联接数据,这在您的情况下是可能的.将连接表构建为临时表或将其设置为select * from ... where false的永久性表将减少处理能力和时间.这里我使用了所有的CTE语句,您可以通过注释掉注释轻松地切换到临时表.

WITH RECURSIVE
#create temp table 
object as (
  select 1 id, 'MyFile1' name union all
  select 2 id, 'MyFile2' name union all
  select 3 id, 'MyFolder' name union all
  select 4 id, 'SomeFile' name union all
  select 5 id, 'Hello' name
),

#create temp table 
path as (
  select 1 user_id, 1 object_id, NULL parent_folder union all
  select 1 user_id, 2 object_id, NULL parent_folder union all
  select 1 user_id, 3 object_id, NULL parent_folder union all
  select 1 user_id, 4 object_id, 3 parent_folder union all
  select 2 user_id, 5 object_id, NULL parent_folder union all
  select 2 user_id, 1 object_id, NULL parent_folder
),

#WITH RECURSIVE
path_name as ( # This includes path information and the name
  SELECT user_id, id, name AS path, parent_folder
  FROM path JOIN object ON path.object_id=object.id
  union all Select * from path_name where false # make this table permanent
),

 all_paths AS ( #RECURSIVE add all data
    SELECT * except(parent_folder) from path_name 
    WHERE parent_folder IS NULL
    UNION ALL
    SELECT all_paths.user_id, null, CONCAT(all_paths.path, '/', path_name.path) 
    FROM all_paths JOIN path_name ON all_paths.id = path_name.parent_folder  
)
SELECT * FROM all_paths ORDER BY user_id, path

Sql相关问答推荐

如何实现一个广泛的多级自连接PostgreSQL查询?

使用Lead获取下一个不同的日期

retrofit AWS Athena中的JSON

当一个视图在Postgres中失效时?

如何在SQL Server中拆分包含字符和数字的列?

如何用客户名称计算sum(dr)和sum(cr)

仅在日期相隔时递增(Oracle SQL)

SQL:查询作为子查询或CTE写入的最大和数失败

Postgres jsonpath运算符的变量替换,如_regex?

使用多个WITH子查询的替代方法

Postgres,使用 select 插入多个值

SQL 中的第一个值和倒数第二个值

Postgres存在限制问题「小值」

SQL Server: 将JSON对象数组转换为表格格式

在 BigQuery 数据集中查找表大小和占总数据集大小的百分比

如何计算每行出现的次数并显示在另一个表中?

snowfalke 会在 Select 运行时锁定表吗?

为什么这是 AND,OR with NULL 的真值表?

如何优化sql请求?

在现有日期列的查询结果中添加周数列