我有一个代表文件夹结构的表 - (即id和父字段的递归) - 这个数据实际上代表文件夹结构中的项目(项目字段只是示例,但我的情况是一个连接到很多东西。 我创建了一个路径字符串(不需要使用) - 这个字符串表示数据集中每个记录的路径(分支字段)
我的查询需要按超过3级深度的所有记录进行过滤,然后计算每个递归分支中3级或更低级别的任何项目(在我的数据中,这将意味着记录5和6代表顶级节点,将是用于分组的记录。
任何帮助?
DECLARE @tbl TABLE
(
Id int
,ParentId int
,branch varchar(100)
,depth int
,item varchar(20)
)
INSERT INTO @tbl
( Id, ParentId,item )
VALUES
(1, NULL,Null),
(2, 1,Null),
(3, 1,Null),
(4, 3,Null),
(5, 4,Null),
(6, 5,'car'),
(7, 6,'bus'),
(8, 7,'truck'),
(9, 8,'car'),
(10,8,'bike'),
(11,5,'car'),
(12,5,'truck'),
(13,4,'truck'),
(14,8,'bike'),
(15,8,'bus');
--select t_package.package_id, t_package.parent_ID from t_package
;WITH abcd
AS (
-- anchor
SELECT id
,ParentID
,CAST(id AS VARCHAR(100)) AS [Path]
,0 as depth
,item
FROM @tbl
WHERE ParentId is Null
UNION ALL
--recursive member
SELECT t.id
,t.ParentID
,CAST(a.[Path] + ',' + CAST( t.ID AS VARCHAR(100)) AS varchar(100)) AS [Path]
,a.depth +1
,t.item
FROM @tbl AS t
JOIN abcd AS a ON t.ParentId = a.id
)
insert into @tbl (id,parentID,branch,depth,item) select * from abcd
select * from @tbl
where branch is not null
这意味着如果您在第3级分组,并且需要每个级别的项目计数,那么结果集将如下所示:
ID Depth -- car -- bike -- bus -- truck
5 3 -- 3 -- 2 -- 2 -- 2
13 3 -- 0 -- 0 -- 0 -- 1
答案 0 :(得分:1)
这非常有趣,所以我不得不推动我以前的CTE经验。
以下是一个应该完成目标的查询。但请注意,在您获得所需结果的方式中,您始终会在查询中对Item
值进行硬编码。最有可能的是,Item
的值的结果域正在发生变化,您将不得不考虑编写动态SQL。在下面的解决方案中,我使用"条件"聚合,已被证明不是"性能破坏者"。我确定可以使用PIVOT
语法引入另一种方法。 性能,应进一步分析,并可能引入一些中间索引方案。
这应该做到这一点,并希望它带给你一些好处:
DECLARE @summaryDepth INT = 3;
DECLARE @tbl TABLE(
ID INT, ParentID INT, Item VARCHAR(20));
INSERT @tbl (
ID, ParentID, Item)
VALUES
(1, NULL, NULL),
(2, 1, NULL),
(3, 1, NULL),
(4, 3, NULL),
(5, 4, NULL),
(6, 5, 'car'),
(7, 6, 'bus'),
(8, 7, 'truck'),
(9, 8, 'car'),
(10, 8, 'bike'),
(11, 5, 'car'),
(12, 5, 'truck'),
(13, 4, 'truck'),
(14, 8, 'bike'),
(15, 8, 'bus');
/*
(1, NULL, NULL),*/
--(2, 1, NULL),
--(3, 1, NULL),
----(4, 3, NULL),
------(13,4,'truck'),
------(5, 4, NULL),
--------(6, 5,'car'),
--------(11,5,'car'),
--------(12,5,'truck'),
----------(7, 6,'bus'),
------------(8, 7,'truck'),
--------------(9, 8,'car'),
--------------(10,8,'bike'),
--------------(14,8,'bike'),
--------------(15,8,'bus');
;WITH CTE_Hierarchy AS (
SELECT
ID, ParentID, Item,
CAST(ID AS VARCHAR(100)) AS [Path],
0 [Depth],
CASE
WHEN @summaryDepth = 0 THEN ID
ELSE NULL
END [SummaryDepthRootID]
FROM @tbl
WHERE ParentId IS NULL
UNION ALL
SELECT
child.ID, child.ParentID, child.Item,
CAST(parent.[Path] + '/' + CAST(child.ID AS VARCHAR(100)) AS VARCHAR(100)) [Path],
parent.[Depth] + 1 [Depth],
CASE
WHEN parent.SummaryDepthRootID IS NOT NULL THEN parent.SummaryDepthRootID
WHEN @summaryDepth = (parent.[Depth] + 1) THEN child.ID
ELSE NULL
END [SummaryDepthRootID]
FROM @tbl AS child
JOIN CTE_Hierarchy AS parent ON parent.ID = child.ParentID
)
SELECT
SummaryDepthRootID [ID],
@summaryDepth [Depth],
COUNT (CASE WHEN Item='car' THEN 1 ELSE NULL END) [car],
COUNT (CASE WHEN Item='bike' THEN 1 ELSE NULL END) [bike],
COUNT (CASE WHEN Item='bus' THEN 1 ELSE NULL END) [bus],
COUNT (CASE WHEN Item='truck' THEN 1 ELSE NULL END) [truck]
FROM CTE_Hierarchy
WHERE SummaryDepthRootID IS NOT NULL
GROUP BY SummaryDepthRootID;
GO
答案 1 :(得分:0)
您也可以在第3级启动递归CTE 然后转动物品。
示例代码:
DECLARE @tbl TABLE(ID INT, ParentID INT, Item VARCHAR(20));
INSERT INTO @tbl (ID, ParentID, Item) VALUES
(1, NULL, NULL),
(2, 1, NULL),
(3, 1, NULL),
(4, 3, NULL),
(5, 4, NULL),
(6, 5, 'car'),
(7, 6, 'bus'),
(8, 7, 'truck'),
(9, 8, 'car'),
(10, 8, 'bike'),
(11, 5, 'car'),
(12, 5, 'truck'),
(13, 4, 'truck'),
(14, 8, 'bike'),
(15, 8, 'bus');
;with CTE as (
select t0.ID as tier0id, t1.ID as tier1id, t2.ID as tier2id, t3.ID as tier3id, 0 as lvl, t3.ID, t3.ParentID, t3.Item
from @tbl t0
join @tbl t1 on (t0.ParentID is null and t1.ParentID = t0.ID)
join @tbl t2 on (t2.ParentID = t1.ID)
join @tbl t3 on (t3.ParentID = t2.ID)
union all
select tier0id, tier1id, tier2id, tier3id, lvl + 1, t.ID, t.ParentID, t.Item
from CTE
join @tbl t on (t.ParentID = CTE.ID)
)
select *
from (
select distinct tier3id as ID, 3 as Depth, ID as ChildId, Item
from CTE
) q
pivot (
count(ChildId)
for Item in ([car], [bike], [bus], [truck])
) pvt
order by ID;