Это было довольно интригующе, поэтому мне пришлось поделиться своим предыдущим опытом с 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