views:

42

answers:

2

Hey all,

Got this table in SQL Server 2005, which is used to maintain a history of merging operations:

  • Column FROM_ID (int)
  • Column TO_ID (int)

Now I need a query that takes the original FROM_ID as input, and returns the last available TO_ID.

So for instance:

  • ID 1 is merged to ID 2
  • Later on, ID 2 is merged to ID 3
  • Again later, ID 3 is merged to ID 4

So the query I'm trying to put together will take as input (in the WHERE clause I presume) ID 1, and should give me the last available TO_ID as a result, in this case 4.

I suppose I need some recursion logic, but don't really know how to start.

Thanks !

Mathieu

+4  A: 

Using a CTE would work.

Testscript

DECLARE @IDs TABLE (
  FromID INTEGER
  , ToID INTEGER
)

INSERT INTO @IDs
SELECT           1, 2 
UNION ALL SELECT 2, 3
UNION ALL SELECT 3, 4

SQL Statement

;WITH q AS (
    SELECT  FromID, ToID
    FROM    @IDs
    UNION ALL 
    SELECT  q.FromID, u.ToID
    FROM    q
            INNER JOIN @IDs u ON u.FromID = q.ToID
)
SELECT  FromID, MAX(ToID)
FROM    q
WHERE   FromID = 1
GROUP BY
        FromID           
Lieven
Tested it, and almost there, apart that the MAX(ToID) won't work because the destination ID to which to merge is not necesserally greater than a previous destination ID in the same chain... So ID 1 could merge to 3, and 3 could then merge to 2 for instance
tjeuten
Could fix it by adding a timestamp to the merge info and selecting the "top 1 order by date desc" method. But was wondering if it could be done without timestamping
tjeuten
+3  A: 

If this works for you give Lieven the accepted answer as it is based on his code.

;WITH q AS (
    SELECT  1 AS LEVEL, FromID, ToID
    FROM    @IDs
    WHERE FromID=1
    UNION ALL 
    SELECT  LEVEL + 1, q.FromID, u.ToID
    FROM    q
            INNER JOIN @IDs u ON u.FromID = q.ToID
)

SELECT TOP 1 ToID
 FROM q
ORDER BY LEVEL DESC
Martin Smith
Yes sir thanks that makes it working ! Thank you both !
tjeuten
Thank's Martin.
Lieven