递归查询是否是用于构建路径的文本连接的选项?

huangapple go评论100阅读模式
英文:

Is recursive query an option for concatenating text for building a path

问题

id name path
1 container1 /container1
2 container2 /container2
3 subcontainer1 /container2/subcontainer1
4 container4 /container4
5 subsub /container2/subcontainer1/subsub

可以尽量将此任务交给数据库执行,但是我缺乏 SQL 技能。如果不可能,我会尝试在应用程序内完成。这可以在 SQL 中实现吗?感谢!

英文:

Simplifying a bit. I have the following data structure:

  1. | id | name | traversal_ids[] |
  2. | -------- | -------------- |-----------------|
  3. | 1 | container1 | {1} |
  4. | 2 | container2 | {2} |
  5. | 3 | subcontainer1 | {2, 3} |
  6. | 4 | container4 | {4} |
  7. | 5 | subsub | {2 ,3 ,5} |

and I'd like to transform this in the following:

  1. | id | name | path |
  2. |-------- |-------------- |----------------------------------|
  3. | 1 | container1 | /container1 |
  4. | 2 | container2 | /container2 |
  5. | 3 | subcontainer1 | /container2/subcontainer1 |
  6. | 4 | container4 | /container4 |
  7. | 5 | subsub | /container2/subcontainer1/subsub |

I'd like as much as possible to give this to the database to execute, but unfortunately I lack the sql skills. If it's not possible I'll try to get this done inside the app.

Can this be achieved in SQL?

Thanks!

答案1

得分: 2

不需要递归。我们可以在一个侧面连接中展开数组,通过连接将相应的名称带回,然后再聚合:

  1. select t.*, x.*
  2. from mytable t
  3. cross join lateral (
  4. select string_agg(t1.name, '/' order by x.ord) path
  5. from unnest(t.traversal_ids) with ordinality x(id, ord)
  6. inner join mytable t1 on t1.id = x.id
  7. ) x
英文:

No need for recursion. We can unnest the array in a lateral join, bring the corresponding names with a join, then aggregate back:

  1. select t.*, x.*
  2. from mytable t
  3. cross join lateral (
  4. select string_agg(t1.name, '/' order by x.ord) path
  5. from unnest(t. traversal_ids) with ordinality x(id, ord)
  6. inner join mytable t1 on t1.id = x.id
  7. ) x

答案2

得分: 0

with cte as (
select t2.id, t2.name, t1.name as sub_name, t1.id as sub_id
from mytable t1
inner join mytable t2 on t1.id = ANY(t2.traversal_ids)
)
select id, name, '/' || string_agg(sub_name, '/' order by sub_id) as path
from cte
group by id, name

Demo here

英文:

Assuming the traversal ids are always with ascendant order, You can do it using a simple inner join with ANY operator as follows :

  1. with cte as (
  2. select t2.id, t2.name, t1.name as sub_name, t1.id as sub_id
  3. from mytable t1
  4. inner join mytable t2 on t1.id = ANY(t2.traversal_ids)
  5. )
  6. select id, name, '/' || string_agg(sub_name, '/' order by sub_id) as path
  7. from cte
  8. group by id, name

Demo here

huangapple
  • 本文由 发表于 2023年3月15日 21:32:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/75745424.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定