1

I just can't find a solution to my problem:

I have a table employees with id's name and the id they report to.

Employees:
id   name  reports_to
2    name2    55
3    name3     2
4    name4     3
5    name5     3
6    name6     2
7    name7    33
8    name8    55

now I need to be able to select the person that reports to id 55, and all the person that report to this person (id2). But just one level down.

the result would look like this:

2    name2    55
3    name3     2
6    name6     2
8    name8    55

I tried joins and subquery but without success.

Edit: If possible the result should be ordered in a way my result table looks: - person that reports to id 55 (i.e. #2) - person that report to #2 should follow immediately

Delcon
  • 2,355
  • 1
  • 20
  • 23

3 Answers3

1

Here is one method, using a subquery to get the second level:

select e.*
from employees e
where e.reports_to = 55 or
      e.reports_to in (select e2.id from employees e2 where e2.reports_to = 55);

EDIT:

To get this sorted requires using join rather than in. I think the logic looks like this:

select e.*
from employees e left join
     employees e2
     on e.reports_to = e2.id
where 55 in (e.reports_to, e2.reports_to)
order by coalesce(e2.id, e.id), (e2.id is null) desc
Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786
  • awesome! I have been trying for hours - and get an answer here in minutes! Is it possible to have the output sortet? I mean that the 2nd level reports_to is right after it's first level reports_to? The way it is now they do not follow the person they report to. – Delcon Dec 04 '15 at 12:48
0

Or, if subqueries aren't really your thing...

SELECT y.* 
  FROM employees x 
  JOIN employees y 
    ON x.id IN(y.reports_to,y.id) 
 WHERE x.reports_to = 55;
+----+-------+------------+
| id | name  | reports_to |
+----+-------+------------+
|  2 | name2 |         55 |
|  3 | name3 |          2 |
|  6 | name6 |          2 |
|  8 | name8 |         55 |
+----+-------+------------+

Incidentally, I'd be interested if anyone knows why the query above formats the result set ever so slightly differently from the query below...

SELECT y.* 
  FROM employees x 
  LEFT 
  JOIN employees y 
    ON x.id IN(y.reports_to,y.id) 
 WHERE x.reports_to = 55;
+------+-------+------------+
| id   | name  | reports_to |
+------+-------+------------+
|    2 | name2 |         55 |
|    3 | name3 |          2 |
|    6 | name6 |          2 |
|    8 | name8 |         55 |
+------+-------+------------+
    ^^

Weird, hunh?

Strawberry
  • 33,750
  • 13
  • 40
  • 57
  • it does get me all the requested employees, but with the subquery, would it be possible to sort it in a way that the 2nd level report_to follow their 1st level report_to? – Delcon Dec 04 '15 at 13:38
0

You have a hierarchy that has been modelled using the adjacency list model. The advantage of this model is that it is fairly intuitive to the modeller and facilitates updates for the user. However, the disadvantage, as you've discovered, it that it is not so easy to query because you need new a join (or equivalent) for each level in the hierarchy. This is particularly tricky when the number of levels is arbitrary.

For mysql solutions, see adjacency list vs nested set.

Community
  • 1
  • 1
onedaywhen
  • 55,269
  • 12
  • 100
  • 138