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
That would be easier to understand if you use a query designer. I am putting a picture of view designer of SQL Server. I hope it can help.
This is how you can find the children:
And I suggest you to allow null for parent_id field and use null instead of 0 so you can make a relation from id (as pk) to parent_id (as fk). That would make everything easier while using the designer.
Let me know if you also need an example for finding the grandchildren.
This is without JOIN statement, but as a SQL learner, I find it as easier:
For grandchildren:
SELECT grandparent.name AS Grandparents, grandchild.name AS Grandchildren
FROM people AS grandparent, people AS parent, people
AS grandchild WHERE grandchild.parent_id = parent.id
AND parent.parent_id = grandparent.id;
For children:
SELECT parent.name as Parent, child.name AS Child
FROM people AS parent, people AS child
WHERE child.parent_id = parent.id AND parent.parent_id = 0;
And for all children-parent pairs:
SELECT parent.name as Parent, child.name AS Child
FROM people AS parent, people AS child
WHERE child.parent_id = parent.id;
It took me a while, but it was fun :D
To get the grandchildren, Try this query.
SELECT name FROM people WHERE parent_id IN (SELECT id from people where parent_id >0);
This can be solved using a simple JOIN
.
To select the list of children:
SELECT c.name
FROM people p
JOIN people c ON c.parent_id = p.id
WHERE p.parent_id = 0
To select the list of grandchildren:
SELECT gc.name
FROM people p
JOIN people c ON c.parent_id = p.id
JOIN people gc ON gc.parent_id = c.id
WHERE p.parent_id = 0
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.