これは、MS SQL 2005以降で、共通のテーブル式を使用して実現できます(http://msdn.microsoft.com/en-us/library/ms186243(v=sql.105).aspxを参照)。
; -- You'll only need this if it's not the first statement in the batch
WITH Recursive AS (
SELECT CurrID AS ID, CAST(CurrID AS nvarchar) AS Path
FROM SourceTable
WHERE PrevID IS NULL -- You need to anchor your first result
UNION ALL
SELECT S.CurrID, P.Path + ' > ' + CAST(CurrID AS nvarchar)
FROM SourceTable S
INNER JOIN Recursive R ON R.CurrID = S.PrevID
)
SELECT * FROM Recursive
次に、最終的なクエリをフィルタリングして、必要なものを取得できます。上から下まで完全に一意のパスのみを除外するには、少しの創造性が必要ですが、これは次のように行うことができます(これをテストできなかったため、少し改良が必要な場合があります)。
; -- You'll only need this if it's not the first statement in the batch
WITH Recursive AS (
SELECT CurrID AS ID, CAST(CurrID AS nvarchar) AS Path, 0 AS Depth
FROM SourceTable
WHERE PrevID IS NULL -- You need to anchor your first result
UNION ALL
SELECT S.CurrID, P.Path + ' > ' + CAST(CurrID AS nvarchar), P.Depth + 1
FROM SourceTable S
INNER JOIN Recursive R ON R.CurrID = S.PrevID
)
SELECT Path
FROM Recursive A
LEFT JOIN Recursive B ON B.Path LIKE A.Path + '%' AND A.Depth < B.Depth
WHERE B.Path IS NULL
大規模なデータセットでは、このような文字列処理は高速ではないため、この方法で処理する場合は注意が必要です。
SQL 2008には、と呼ばれるデータ型hierarchyid
があります。これも便利です。私はそれを使ったことがないので、本当に助けることはできませんが、興味があれば、これで始めることができます:http: //msdn.microsoft.com/en-us/library/bb677290.aspx