I\'m pretty new to SQL, trying to wrap my head around it, but it\'s getting a little confusing. Here\'s a simplified version of what I\'m working with.
I have this
First of all, it's very important to know that this question is very easy to answer, IF you know that you're working with a fixed set of generations (down to grandchildren, for example). If this table is ultimately going to have many generations, and you want to (for example) find all of Kyle's descendants through the whole family tree, then you are not going to do it with a single query. (I have a stored procedure that deals with arbitrary levels of tree generations.) So for now, let's find up to grandparents / grandchildren.
As you said, finding the grandparents is easy...
mysql> select name from people where parent_id = 0;
+-------+
| name |
+-------+
| Kevin |
| Kyle |
+-------+
2 rows in set (0.00 sec)
Now, finding children isn't too bad.
Let's find Kyle's children:
mysql> select p1.name from people p1 where p1.parent_id in
(select p2.id from people p2 where p2.name = 'Kyle');
+-------+
| name |
+-------+
| John |
| Jason |
+-------+
2 rows in set (0.02 sec)
And here's Kyle's grandchildren:
mysql> select p3.name from people p3 where p3.parent_id in
(select p2.id from people p2 where p2.parent_id in
(select p3.id from people p3 where p3.name = 'Kyle'));
+-------+
| name |
+-------+
| Mabel |
+-------+
1 row in set (0.01 sec)
mysql>
Going the other direction... who is Mabel's parent?
mysql> select p1.name from people p1 where p1.id =
(select p2.parent_id from people p2 where p2.name = 'Mabel');
+-------+
| name |
+-------+
| Jason |
+-------+
1 row in set (0.00 sec)
mysql>
... and her grandparent:
mysql> select p1.name from people p1 where p1.id =
(select p2.parent_id from people p2 where p2.id =
(select p3.parent_id from people p3 where p3.name = 'Mabel'));
+------+
| name |
+------+
| Kyle |
+------+
1 row in set (0.00 sec)
So you can see the pattern I followed to make these queries should you need great-grandparents / great-grandchildren. However, the resulting query will become unwieldy if you need more generations, and a stored procedure that loops will be in order.
The Oracle database has a more elegant solution, a SQL extension called "CONNECT BY PRIOR". For some more reading (and a MySQL stored procedure example), check out Connect By Prior Equivalent for MySQL here on StackOverflow.
A final note: do yourself a favor, if you haven't already, and:
mysql> create index ix_parent_id on people(parent_id);
Query OK, 0 rows affected (0.06 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql>
It will dramatically improve performance of for these kind of queries.