0

I have a database structure something like the following:

Table A: PersonId, GroupId
Table B: GroupId, ParentGroupId

Given a PersonId, I want to find the Ids of all people in parent groups of that person's group.

First I select the ParentGroupId for the given PersonId, by joining with B. Then I do a while loop, selecting and recording the PersonId from A based on the GroupId returned in the previous search, and continue the loop by obtaining the next ParentGroupId from B.

Is this an efficient way to do this search, or is there an option that does not involve a while to "bubble up" in this manner?

(this is a simplified version of the actual scenario, changing the schema is not an option)

 $sql = 'SELECT ParentGroupID FROM A WHERE PersonId = ' . $id;
  $result = $db->query($sql);
  $row = $db->fetch_array($result); 
  $parent_group = $row['ParentGroupId'];

  if(!is_null($parent_group)) {

      $parent_ids = array();

      while($parent_group > 0) {
          //is there a way to do this where I retrieve all managers <= lvl 6 at once, so I don't have to loop in order to 'tier up'?
          $sql = 'SELECT ParentGroupID, PersonID
                  FROM B 
                  INNER JOIN A on ParentGroupID = A.GroupID 
                  WHERE  ParentGroupID = ' . $parent_group;

          $result = $db->query($sql);
          $row = $db->fetch_array($result); 
          $parent_group = $row['ParentGroupID'];
          $parent_ids[] = $row['PersonID'];
      }
  }
4
  • What makes yoo think that query is inefficient? Commented May 4, 2015 at 16:26
  • 2
    @Mihai doing another query for each pass through a loop is the definition of inefficient. Commented May 4, 2015 at 16:27
  • What you could do is compress the 2 queries into 1 with a LEFT or RIGHT JOIN and then check your values with WHERE IS NULL Commented May 4, 2015 at 16:30
  • 3
    The while loop will iterate as long as parent groups exist for the previous obtained ParentGroupID Commented May 4, 2015 at 16:32

1 Answer 1

1

Combining your two queries into one would be more efficient:

$sql = 'SELECT ParentGroupID, PersonID
  FROM B 
  INNER JOIN A on ParentGroupID = A.GroupID 
  WHERE  ParentGroupID IN (
    SELECT ParentGroupID FROM A WHERE ParentGroupID > 0
    AND PersonId = ' . $id .')' ;
Sign up to request clarification or add additional context in comments.

2 Comments

@Don'tPanic His code doesn't seem to be recursive, it just gets all people with the same parent groups as a users (if I'm reading correctly). From the question: "Given a PersonId, I want to find the Ids of all people in parent groups of that person's group."
Well, it 'recurses' up the parent group structure. A group has a parent, which has a parent, etc... and the code iterates, recording PersonIds, as long as a person's group has a parent.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.