我有下表:
parent_id child_id child_class
1 2 1
1 3 1
1 4 2
2 5 2
2 6 2
Parent_id表示文件夹ID。子ID表示子文件夹(其中child_class = 1)或子文件(其中child_class = 2)。
我想通过以下方式获取所有文件的汇总计数器(自下而上)(child_class = 2)。例如,如果C是一个包含5个文件的叶子文件夹(没有子文件夹),而B是包含4个文件的C的父文件夹,则C上的计数器应该为5,B上的计数器应该为9(= 5)来自C加上B)中的4个文件,等等以递归方式自下而上考虑兄弟文件夹等。
在上面的示例中,我希望下面的结果(通知3是一个没有文件的子文件夹):
parent_id FilesCounter
3 0
2 2
1 3
我更喜欢SQL查询的性能,但也可以使用函数。
我尝试将hirarchical查询与汇总(sql 2008 r2)混合到目前为止没有成功。
请告知。
答案 0 :(得分:0)
这个CTE应该可以解决问题......这是SQLFiddle。
SELECT parent_id, child_id, child_class,
(SELECT COUNT(*) FROM tbl a WHERE a.parent_id = e.parent_id AND child_class <> 1) AS child_count
INTO tbl2
FROM tbl e
;WITH CTE (parent_id, child_id, child_class, child_count)
AS
(
-- Start with leaf nodes
SELECT parent_id, child_id, child_class, child_count
FROM tbl2
WHERE child_id NOT IN (SELECT parent_id from tbl)
UNION ALL
-- Recursively go up the chain
SELECT e.parent_id, e.child_id, e.child_class, e.child_count + d.child_count
FROM tbl2 e
INNER JOIN CTE AS d
ON e.child_id = d.parent_id
)
-- Statement that executes the CTE
SELECT FOLDERS.parent_id, max(ISNULL(child_count,0)) FilesCounter
FROM (SELECT parent_id FROM tbl2 WHERE parent_id NOT IN (select child_id from tbl2)
UNION
SELECT child_id FROM tbl2 WHERE child_class = 1) FOLDERS
LEFT JOIN CTE ON FOLDERS.parent_id = CTE.parent_id
GROUP BY FOLDERS.parent_id
答案 1 :(得分:0)
Zak的答案很接近,但根文件夹没有很好地汇总。以下是工作:
with par_child as (
select 1 as parent_id, 2 as child_id, 1 as child_class
union all select 1, 3, 1
union all select 1, 4, 2
union all select 2, 5, 1
union all select 2, 6, 2
union all select 2, 10, 2
union all select 3, 11, 2
union all select 3, 7 , 2
union all select 5, 8 , 2
union all select 5, 9 , 2
union all select 5, 12, 1
union all select 5, 13, 1
)
, child_cnt as
(
select parent_id as root_parent_id, parent_id, child_id, child_class, 1 as lvl from par_child union all
select cc.root_parent_id, pc.parent_id, pc.child_id, pc.child_class, cc.lvl + 1 as lvl from
par_child pc join child_cnt cc on (pc.parent_id=cc.child_id)
),
distinct_folders as (
select distinct child_id as folder_id from par_child where child_class=1
)
select root_parent_id, count(child_id) as cnt from child_cnt where child_class=2 group by root_parent_id
union all
select folder_id, 0 from distinct_folders df where not exists (select 1 from par_child pc where df.folder_id=pc.parent_id)