Определение дочерних подсчетов иерархических путей - PullRequest
1 голос
/ 29 января 2011

У меня есть таблица, состоящая из следующих столбцов:

child_count | path
------------+-----
            | /
            | /a
            | /a/a
            | /a/b
            | /a/b/c
            | /b

В настоящее время только столбец пути содержит данные.Я хотел бы знать SQL-запрос (предпочтительно PostgreSQL), который мог бы определить количество дочерних элементов для каждого пути следующим образом:

child_count | path
------------+-----
2           | /
2           | /a
0           | /a/a
1           | /a/b
0           | /a/b/c
0           | /b

Ответы [ 2 ]

1 голос
/ 29 января 2011

Andomar обошел меня, когда я редактировал, но я все равно опубликую свое решение, так как оно использует некоторые специфические для PostgreSQL вещи.

with path_elements as (
  select path, array_length(string_to_array(path, '/'),1) as element_count
  from path_table
)
select parent_path, count(child_path) 
from (
  select p.path as parent_path,
         c.path as child_path
  from path_elements p
    left join path_elements c 
              on p.element_count + 1 = c.element_count 
             and substring(c.path, 1, length(p.path)) = p.path
) t
group by parent_path
order by parent_path;
1 голос
/ 29 января 2011

Глубину пути можно посчитать с помощью:

len(path) - len(replace(path,'/','')) 

Тогда у детей будет на одну глубину больше, чем у их родителей, и путь детей начинается с родительского пути:

on      children.depth = parents.depth + 1
        and substring(children.path, 1, len(parents.path)) = parents.path

Собирая это вместе (для SQL Server, но должно работать на Postgres с небольшими изменениями):

;with depth as 
        (
select  depth = case when path = '/' then 0 
                     else len(path) - len(replace(path,'/','')) 
                end
,       path
from    YourTable
        )
select  COUNT(children.path) as child_count
,       parents.path
from    depth parents
left join
        depth children
on      children.depth = parents.depth + 1
        and substring(children.path, 1, len(parents.path)) = parents.path
group by    
        parents.path

Это печатает:

child_count path                
----------- --------------------
2           /                   
2           /a                  
0           /a/a                
1           /a/b                
0           /a/b/c              
0           /b                  

Тестовые данные:

if OBJECT_ID('YourTable') is not null
    drop table YourTable
create table YourTable (child_count int, path varchar(max))
insert YourTable (path) values
('/'),
('/a'),
('/a/a'),
('/a/b'),
('/a/b/c'),
('/b')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...