我有一个名为companies
的MySQL表,如下所示:
+---------+-----------+-----------+
| id_comp | comp_name | id_parent |
+---------+-----------+-----------+
| 1 | comp1 | NULL |
| 2 | comp2 | 1 |
| 3 | comp3 | 2 |
| 4 | comp4 | 2 |
| 5 | comp5 | 2 |
| 6 | comp6 | 1 |
| 3 | comp3 | 6 |
| 5 | comp5 | 6 |
| 7 | comp7 | 6 |
| 4 | comp4 | 6 |
| 8 | comp8 | 4 |
+---------+-----------+-----------+
每家公司可能有多个父母(例如:comp3
,这是comp2
和comp6
的孩子),每个父母可能有多个孩子,每个孩子可以是父母本身多个孩子等等......所以,它可以有无限级别(关系)。
我研究了几种解决方案(http://www.codeproject.com/Articles/818694/SQL-queries-to-manage-hierarchical-or-parent-child,http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/),但我不认为它适合我的问题,因为同一家公司(基于id_comp
列)可以有多个父母。
我有两个问题:
name
(这是唯一的,基于id_comp
)查询选择其兄弟(相同的parent_id),其直接父母及其直接子(s),我该如何? )。答案 0 :(得分:1)
如果您需要处理分层数据(将所有祖先/后代变得棘手),Mysql不是最佳选择。但是,如果你关心的只是找到直接的父母/孩子,你的表应该没问题(虽然我可能会将其分解为单独的Company和CompanyParent表,以便不多次输入公司名称。)
这会给你兄弟们:
select name
from companies
where id_parent in (select id_parent from companies where id_comp = @company_id)
and id_comp <> @company_id
group by name;
这会给你直接的父母:
select p.name
from companies p
join companies c on p.id = c.id_parent
where c.id_comp = @company_id
group by c.name;
这会给你直接的孩子:
select c.name
from companies p
join companies c on p.id = c.id_parent
where p.id_comp = @company_id
group by c.name;
答案 1 :(得分:1)
你有一个简单的&#34;很多:很多&#34;关系。但是,由于没有循环,您有一个与实际不相关(也不可检查)的限制。
CREATE TABLE Relations (
id_comp ...,
id_parent ...,
PRIMARY KEY(id_comp, id_parent), -- for reaching "up"
INDEX(id_parent, id_comp) -- for reaching "down"
) ENGINE=InnoDB;
这将扩大到数百万,可能是数十亿的关系。由于PRIMARY KEY
根据定义为UNIQUE
和INDEX
,因此可以防止重复关系(1
仅为2
的父级一次)并提供有效的方法来横穿一个方向。
必要时使用DISTINCT
代替GROUP BY
。不要使用IN ( SELECT ...)
,它往往很慢。
我的兄弟姐妹:
SELECT DISTINCT their_kids.*
FROM Relations AS me
JOIN Relations AS my_parents ON my_parents.id_comp = me.id_parent
JOIN Relations AS their_kids ON their_kids.id_parent = parents.id_comp
WHERE me.id_comp = @me
AND their_kids != @me;
我(直系)父母:
SELECT my_parents.*
FROM Relations AS me
JOIN Relations AS my_parents ON my_parents.id_comp = me.id_parent
WHERE me.id_comp = @me;
我的(直系)孩子:
SELECT my_kids.*
FROM Relations AS me
JOIN Relations AS my_kids ON my_kids.id_parent = me.id_comp
WHERE me.id_comp = @me;
阿姨,叔叔,第一堂兄弟会有点麻烦。所有的祖先或后代都会变得更加混乱,应该通过应用程序代码或存储过程中的循环来完成。