我对SQL很陌生,试图绕过它,但它有点令人困惑。这是我正在使用的简化版本。
我有一个名为people
的表:
+----+------------+-----------+
| id | name | parent_id |
+----+------------+-----------+
| 1 | Bob | 3 |
| 2 | John | 5 |
| 3 | Larry | 4 |
| 4 | Kevin | 0 |
| 5 | Kyle | 0 |
| 6 | Jason | 5 |
| 7 | Mildred | 4 |
| 8 | Mabel | 6 |
+----+------------+-----------+
上表是人员列表。他们的parent_id列指的是他们的父母是谁。如果桌面上没有父母,则他们的parent_id为0.
现在,我希望能够获得每组人员的单独名单:祖父母,子女和孙子女。
很容易找到祖父母(拉里和凯文),我可以这样查询:
SELECT name FROM people WHERE parent_id = 0
但是当谈到让孩子(John,Larry,Jason和Mildred)和孙子(Bob和Mabel)时,我迷失了。
在英语中,这将是获取孩子的过程:“从表中获取所有结果。对于每一个,查看他们的父ID。在表中找到具有该ID的结果。参见< em>那个人的 id,如果是0,那么原来的人就是孩子。将它们添加到我们将要显示的内容列表中。“
对于孙子女来说,它将与上述相同,但只是增加了一步。
这有意义吗?如何将上述过程编写为SQL查询?
答案 0 :(得分:7)
这可以使用简单的JOIN
来解决。
选择子项列表:
SELECT c.name
FROM people p
JOIN people c ON c.parent_id = p.id
WHERE p.parent_id = 0
选择孙子列表:
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
答案 1 :(得分:2)
首先,非常重要的是要知道这个问题很容易回答,如果你知道你正在与固定的几代人一起工作(例如,对孙子孙女来说)。如果这个表最终会有很多代,并且你想(例如)通过整个族树找到所有Kyle的后代,那么你不会用一个查询来完成它。 (我有一个处理任意级别的树世代的存储过程。)所以现在,让我们找到祖父母/孙子。
正如你所说,找到祖父母很容易......
mysql> select name from people where parent_id = 0;
+-------+
| name |
+-------+
| Kevin |
| Kyle |
+-------+
2 rows in set (0.00 sec)
现在,找到孩子也不错。
让我们找到凯尔的孩子们:
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)
这是凯尔的孙子们:
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>
走向另一个方向......谁是梅布尔的父母?
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>
......和她的祖父母:
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)
如果你需要曾祖父母/曾孙子,你可以看到我所遵循的模式来进行这些查询。但是,如果您需要更多代,则生成的查询将变得难以处理,并且循环的存储过程将按顺序排列。
Oracle数据库有一个更优雅的解决方案,一个名为“CONNECT BY PRIOR”的SQL扩展。有关更多阅读(以及MySQL存储过程示例),请在StackOverflow上查看Connect By Prior Equivalent for MySQL。
最后一点:如果你还没有,请帮自己一个忙,并且:
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>
它将显着提高这类查询的性能。
答案 2 :(得分:0)
要获得孙子,请尝试此查询。
SELECT name FROM people WHERE parent_id IN (SELECT id from people where parent_id >0);
答案 3 :(得分:0)
如果您使用查询设计器,那将更容易理解。我正在为SQL Server的视图设计者拍照。我希望它可以提供帮助。
这是你找到孩子的方法:
我建议你为parent_id字段允许null并使用null而不是0,这样你就可以建立从id(作为pk)到parent_id(作为fk)的关系。这将使使用设计师时更容易。
如果您还需要一个寻找孙子的例子,请告诉我。
答案 4 :(得分:0)
这没有JOIN语句,但作为SQL学习者,我发现它更容易:
对于孙子:
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;
对于孩子们:
SELECT parent.name as Parent, child.name AS Child
FROM people AS parent, people AS child
WHERE child.parent_id = parent.id;
对于所有儿童 - 父母对:
{{1}}
我花了一段时间,但很有趣:D