我有一个由以下列组成的表:
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
答案 0 :(得分:1)
你可以用以下方法计算路径的深度:
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')
答案 1 :(得分:1)
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;