【问题标题】:Selecting certain levels of a hierarchy with PostgreSQL使用 PostgreSQL 选择层次结构的某些级别
【发布时间】:2014-04-20 21:30:04
【问题描述】:

我有一个使用枚举路径表示层次结构的表:

  id | name  | path  
-----+-------+-------
   1 | Bob   | 1
   2 | Joe   | 2
   3 | Kyle  | 2/3
   4 | Sarah | 2/4
   5 | Jim   | 5
   6 | Steve | 5/6
   7 | Adam  | 5/7
   8 | Frank | 5/7/8
   9 | Sue   | 5/7/9

我需要一个查询来返回给定记录的直接子项,并且对于每个子项,返回其下所有子记录的计数。

例如,针对 Jim (id=5) 的查询应返回以下集合:

  id | name  | path  | subrecords
-----+-------+-------+------------
   6 | Steve | 5/6   | 0
   7 | Adam  | 5/7   | 2

尝试:

如果我这样做:

select did, name, path, SUBSTRING(path FROM '5\/[^\/]*$') as child_path from items where path ~ '5\/.*';

我得到了那里的一部分......

 did | name  | path  | child_path 
-----+-------+-------+---------
   6 | Steve | 5/6   | 5/6
   7 | Adam  | 5/7   | 5/7
   8 | Frank | 5/7/8 | 
   9 | Sue   | 5/7/9 | 

...但记录 8 和 9 需要汇总为小于 7 的计数。

我试过了:

select SUBSTRING(path FROM '5\/[^\/]*$') as child_path, COUNT(id) as count from items where path ~ '5\/.*' GROUP BY child_path;

这让我很兴奋:

child_path | count 
----------+-------
          |     2
 5/7      |     1
 5/6      |     1

没有。

我怎样才能做到这一点?

【问题讨论】:

    标签: sql regex postgresql


    【解决方案1】:

    我认为你可以在没有自我加入的情况下做到这一点。

    您可以使用以下表达式选择给定节点的所有后代:path like '5' || '/' || id || '%'。然后,您可以通过选择最多 5 个子字符串和下一个 id 来聚合它们:

    select left(path, length('5'||'/') + position('/' in split_part(path||'/', '5'||'/', 2)) - 1) as child,
           count(*) - 1 as numdescendants
    from items
    where path like '5' || '/' || '%'
    group by child;
    

    count(*) 计算特定子代的后代数量,包括该子代。因此,- 1 得到了他们后代的数量。

    这应该可以工作,因此您可以将'5' 替换为任何路径。

    【讨论】:

    • 这很漂亮,谢谢! (顺便说一句,为其他人澄清一些让我感到困惑的事情:双管道 || 是字符串连接符,而不是 OR 运算符)
    【解决方案2】:

    在我看来,这就是工作。

    SELECT i.id,
           i.name,
           i.path,
           count(ii.id) AS cnt
    FROM items i
    LEFT OUTER JOIN items ii
    ON ii.id != i.id AND ii.path LIKE i.path || '%'
    WHERE i.path ~ '5\/[^\/]*$'
    GROUP BY i.id,
             i.name,
             i.path;
    

    http://sqlfiddle.com/#!15/b5b4c/23

    【讨论】:

    • @popovitsj- 谢谢,这确实有效- 但必须将其交给 Gordon 的免连接解决方​​案
    猜你喜欢
    • 1970-01-01
    • 2013-07-04
    • 2023-04-03
    • 2012-12-17
    • 1970-01-01
    • 2016-09-11
    • 1970-01-01
    • 1970-01-01
    • 2020-09-10
    相关资源
    最近更新 更多