Надеюсь, я правильно понял ...
Вы можете использовать рекурсивный CTE вместе с ROW_NUMBER()
для создания ваших кодов.
DECLARE @dummy TABLE(Id INT,ParentId INT,[Name] VARCHAR(100));
INSERT INTO @dummy(Id,ParentId,[Name]) VALUES
(1,Null,'John')
,(2,1 ,'Harry')
,(3,1 ,'Mary')
,(4,2 ,'Emma')
,(5,2 ,'Kyle')
,(6,4 ,'Robert')
,(7,Null,'Rohit');
WITH recCTE AS
(
SELECT Id,ParentId,[Name]
,CONCAT(N'.',CAST(ROW_NUMBER() OVER(ORDER BY Id) AS NVARCHAR(MAX))) AS Code
FROM @dummy WHERE ParentId IS NULL
UNION ALL
SELECT d.Id,d.ParentId,d.[Name]
,CONCAT(r.Code,N'.', ROW_NUMBER() OVER(ORDER BY d.Id))
FROM @dummy d
INNER JOIN recCTE r ON d.ParentId=r.Id
)
SELECT Id,ParentId,[Name]
,STUFF(Code,1,1,'') AS Code
FROM RecCTE;
Идея вкратце:
Мы выбираем строки с ParentId IS NULL
и присваиваем им порядковый номер.
Теперь мы итеративно просматриваем их (на самом деле это скрытый RBAR ) и вызываем их потомков, снова с порядковым номером.
Это мы делаем до тех пор, пока ничего не останется.
для финала SELECT
требуется STUFF
, чтобы избавиться от первой точки.
И с таким расширением вы можете создать буквенно-цифровой код:
WITH recCTE AS
(
SELECT Id,ParentId,[Name]
,CONCAT(N'.',CAST(ROW_NUMBER() OVER(ORDER BY Id) AS NVARCHAR(MAX))) AS Code
,CONCAT(N'000',CAST(ROW_NUMBER() OVER(ORDER BY Id) AS NVARCHAR(MAX))) AS Code2
FROM @dummy WHERE ParentId IS NULL
UNION ALL
SELECT d.Id,d.ParentId,d.[Name]
,CONCAT(r.Code,N'.', ROW_NUMBER() OVER(ORDER BY d.Id))
,CONCAT(r.Code2,RIGHT(CONCAT('0000',ROW_NUMBER() OVER(ORDER BY d.Id)),4))
FROM @dummy d
INNER JOIN recCTE r ON d.ParentId=r.Id
)
SELECT Id,ParentId,[Name]
,STUFF(Code,1,1,'') AS Code
,Code2
FROM RecCTE
ORDER BY Code2;