I believe that you can do this using a recursive generic table expression , especially if you do not expect very long chains of records
WITH Ancestors AS
(
SELECT
InitRow.[ID] AS [Ancestor],
InitRow.[ID],
InitRow.[first],
InitRow.[end],
0 AS [level],
'00000' + InitRow.[ID] AS [hacky_level_plus_ID]
FROM
YOUR_TABLE AS InitRow
WHERE
NOT EXISTS
(
SELECT * FROM YOUR_TABLE AS PrevRow
WHERE PrevRow.[end] = InitRow.[first]
)
UNION ALL
SELECT
ParentRow.Ancestor,
ChildRow.[ID],
ChildRow.[first],
ChildRow.[end],
ParentRow.level + 1 AS [level],
RIGHT('00000' + CAST(ParentRow.level + 1 AS varchar(4)), 5)
+ ChildRow.[ID] AS [hacky_level_plus_ID]
FROM
Ancestors AS ParentRow
INNER JOIN YOUR_TABLE AS ChildRow
ON ChildRow.[first] = ParentRow.[end]
)
SELECT
Ancestors.Ancestor + '-' + SUBSTRING(MAX([hacky_level_plus_ID]),6,10) AS [IDs],
MIN(Ancestors.[first]) AS [first],
MAX(Ancestors.[end]) AS [end]
FROM
Ancestors
GROUP BY
Ancestors.Ancestor
A brief explanation of what each part does:
WITH Ancestors AS (...) Common Table ( ) Ancestors. SELECT : , .
SELECT - , . Ancestors , , , YOUR_TABLE. .
- SELECT, , . GROUP BY, Ancestor, - MIN MAX.
. , . , , . ( , , .)
, , , ( level - , 1 , ), , . max level a MAX, level.
CTE , , , MAXRECURSION. - 100. , CTE .
. first , first == end, , , , CTE .
. , , . , .