Ответ 1
Ты почти сделал это. Просто добавьте rank
, чтобы идентифицировать каждую группу, а затем отсортировать данные по ней.
Кроме того, поскольку вы работаете с более сложной иерархией, нам нужно изменить значение [level]
. В настоящее время это не число, поместите полный путь текущего элемента в родительский. Где \
означает родительский. Например, следующая строка:
\ 1\5\4\1
представляет иерархию ниже:
1
--> 5
--> 4
--> 1
Я получаю идею от hierarchyid. Вы можете захотеть сохранить иерархию, используя ее, так как она имеет удобные встроенные функции для работы с такими структурами.
Вот полный рабочий пример с новыми данными:
DECLARE @DataSource TABLE
(
[c] TINYINT
,[p] TINYINT
);
INSERT INTO @DataSource ([c], [p])
VALUES (1,0)
,(3, 1)
,(2, 3)
,(5,1)
,(7, 2)
,(40, 0)
,(2, 40);
WITH DataSource ([c], [p], [level], [rank])AS
(
SELECT [c]
,[p]
,CAST('/' AS VARCHAR(24))
,ROW_NUMBER() OVER (ORDER BY [c] ASC)
FROM @DataSource
WHERE [p] = 0
UNION ALL
SELECT DS.[c]
,DS.[p]
,CAST(DS1.[level] + CAST(DS.[c] AS VARCHAR(3)) + '/' AS VARCHAR(24))
,DS1.[rank]
FROM @DataSource DS
INNER JOIN DataSource DS1
ON DS1.[c] = DS.[p]
)
SELECT [c]
,[p]
FROM DataSource
ORDER BY [Rank]
,CAST([level] AS hierarchyid);
Снова обратите внимание на node (7,2)
, который участвует в двух группах (даже в вашем примере). Я думаю, это всего лишь образец данных, и у вас есть способ определить, где должен быть включен node.