views:

58

answers:

3

Lets say you have a table as such (SQL SERVER 2005)

pairID childID parentID
 0       1      2
 1       2      3
 2       3      4

And you have a CTE that return this dataset:

pairID childID parentID level
 0       1      2        2
 1       2      3        1
 2       3      4        0

How do you save the initial child ID so that you would get this result set instead:

pairID childID parentID level
 0       1      2        2
 1       1      3        1
 2       1      4        0

So basically what I am doing is keeping the original child id and returning that instead of the other...

This is the CTE query to date, which works perfectly:

WITH TESTER AS (SELECT a.PairID,
                a.ChildID,
                a.ParentID,
                0 AS Level
                FROM
                BusinessHierarchy AS a 
                LEFT OUTER JOIN BusinessHierarchy AS a2 
                ON a.ParentID = a2.ChildID
                WHERE (a2.PairID IS NULL)
                UNION ALL
                SELECT b.PairID, b.ChildID, b.ParentID, oh.Level + 1 AS Level
                FROM BusinessHierarchy AS b INNER JOIN
                TESTER AS oh ON b.ParentID = oh.ChildID)
SELECT PairID, ChildID, ParentID, Level
 FROM  TESTER AS x
 ORDER BY Level, ChildID, ParentID
A: 

You could get that if first (into a variable), then use the variable later.

DECLARE @StartingId int

SELECT
    @StartingId = a.PairID
FROM BusinessHierarchy AS a 
LEFT OUTER JOIN BusinessHierarchy AS a2 ON a.ParentID = a2.ChildID
WHERE (a2.PairID IS NULL)


WITH TESTER AS (SELECT a.PairID,
            a.ChildID,
            a.ParentID,
            0 AS Level
            FROM
            BusinessHierarchy AS a 
            WHERE (a.PairID = @StartingId)
            UNION ALL
            SELECT b.PairID, b.ChildID, b.ParentID, oh.Level + 1 AS Level
            FROM BusinessHierarchy AS b INNER JOIN
            TESTER AS oh ON b.ParentID = oh.ChildID)

SELECT PairID, @StartingId, ParentID, Level
FROM  TESTER AS x
ORDER BY Level, ChildID, ParentID
Gabriel McAdams
Doesn't this only happen once, the initial population of @StartingID? What happens with each of the different hierarchical groups?
flavour404
It does only happen once. If you want it to happen more than that, you have to give us more information about what you have in the table and what you want to do with it.
Gabriel McAdams
A: 

Untested, but have you tried this?

;WITH My_CTE AS
(
     SELECT
          BH1.PairID,
          BH1.ChildID AS BaseID,
          BH1.ChildID,
          BH1.ParentID,
          0 AS Level
     FROM
          BussinessHierarchy BH1
     LEFT OUTER JOIN BussinessHierarchy BH2 ON
          BH1.ParentID = BH2.ChildID
     WHERE
          BH2.PairID IS NULL
     UNION ALL
     SELECT
          BH3.PairID,
          CTE.BaseID,
          BH3.ChildID,
          BH3.ParentID,
          CTE.Level + 1 AS Level
     FROM
          My_CTE CTE
     INNER JOIN BussinessHierarchy BH3 ON
          BH3.ParentID = CTE.ChildID
     )
SELECT
     PairID,
     BaseID,
     ParentID,
     Level
FROM
     My_CTE
ORDER BY
     Level,
     BaseID,
     ParentID
Tom H.
I did but it just kept crashing my IDE before I could debug an errors. I'll keep trying.
flavour404
A: 

Your CTE as written just confused me I'm afraid, so I rewrote it as follows and it gives the results you are asking for. Does this meet your requirements?

WITH List (pairID, childId, parentId, level, originalid )
AS
(
    -- Anchor member definition
    select pairID, childID, parentID, 0 as level, ChildID as originalid
    FROM    
    BusinessHeirarchy bh
    where bh.PairID = 0


    UNION ALL

    -- Recursive member definition
    select j.pairId, j.childID, j.parentID, lst.level +1 as level, lst.originalid
    from BusinessHeirarchy j inner join List lst 
    on  (lst.parentId = j.ChildID)

)

select * from list;

You can obviously play with the outputs columns and the order as you need, but that data matches what you want.

One thing to be careful of with my sql is I restricted the anchor query based upon a pairid of zero, since your example data did not have the nulls. This should easy enough to change if you need the null check to pull out your anchor.

Then I simply join on the parent to child relationship with the additional column OriginalId holding the first childId from the anchor query.

David Hall
Not really sure what the error is as when I correct the 'Hierarchy' error and run it my IDE just crashes. The other issue is that their are a lot of these items with this kind of relationship and the above was just a lowend example.
flavour404
Your IDE crashes?! Do you mean management studio? The code provided runs fine on the provided data. Could the issue be something about the data? If you are running this from Visual Studio, it could be that it doesn't deal well with the error thrown when the max recursion is hit.
David Hall
That is true, and yes I am running this in visual studio. The example above is one small example and I have 800 rows returned in my dataset using the original query, I cannot get the one above to work, sorry this is still a new concept to me.
flavour404
What happens when you run this in management studio (the SQL server equivalent of the visual studio IDE)? Do you get better error information? With the sort of SQL I always find the best way to tackle it is to start small and work up. What happens when you run just the anchor part of the query? And what about if you run the second join manually (entering it into management studio)?
David Hall