Для этого вы можете использовать рекурсивный CTE .Проблема в том, что вам не хватает номера строки, чтобы правильно соединиться со следующими значениями (и никогда не сравнивать с предыдущими).Я предполагаю, что это то, что вы хотите, потому что вы включаете путь /AAA/BBB
в свои результаты, но не /BBB/AAA
, поэтому запись для AAA
должна объединяться с BBB
, но запись с BBB
не с AAA
, следовательно, необходимоконкретного метода сортировки, которого нет в ваших данных.
Я имитировал номер строки с IDENTITY
, вы можете использовать ROW_NUMBER()
с любым OVER(PARTITION BY ID ORDER BY <expression or column> )
, который вы хотите.
Настройка :
IF OBJECT_ID('tempdb..#Values') IS NOT NULL
DROP TABLE #Values
CREATE TABLE #Values(
RowID INT IDENTITY,
ID INT,
Text VARCHAR(100))
INSERT INTO #Values (
ID,
Text)
VALUES
(100, 'AAA'),
(100, 'BBB'),
(100, 'CCC'),
(200, 'DDD'),
(200, 'EEE')
Решение :
;WITH RecursiveJoins AS
(
-- Anchor (original row)
SELECT
OriginRowID = V.RowID,
CurrentRowID = V.RowID,
ID = V.ID,
Path = CONVERT(VARCHAR(MAX), '/' + V.Text),
RecursionLevel = 0
FROM
#Values AS V
UNION ALL
-- Recursion (add any value with the same ID and higher RowID)
SELECT
OriginRowID = R.OriginRowID,
CurrentRowID = V.RowID,
ID = R.ID,
Path = R.Path + '/' + V.Text,
RecursionLevel = R.RecursionLevel + 1
FROM
RecursiveJoins AS R
INNER JOIN #Values AS V ON
R.ID = V.ID AND
R.CurrentRowID < V.RowID
)
SELECT
R.ID,
R.Path,
R.RecursionLevel
FROM
RecursiveJoins AS R
ORDER BY
R.ID,
R.RecursionLevel,
R.Path
Результат:
ID Path RecursionLevel
100 /AAA 0
100 /BBB 0
100 /CCC 0
100 /AAA/BBB 1
100 /AAA/CCC 1
100 /BBB/CCC 1
100 /AAA/BBB/CCC 2
200 /DDD 0
200 /EEE 0
200 /DDD/EEE 1