在我的项目中,我有产品的位置,可能看起来像这样:
- Location 1
-- SubLocation 1
-- SubLocation 2
- Location 2
-- SubLocation 3
-- SubLocation 4
想象一下,一个区域中有子区域。我需要将其存储在DB中,然后稍后重试,如下所示:SubLocation 1 at Location 1
。
我的第一个猜测是有两个具有一对多关系的表,但这不会扩展,稍后我需要这样的东西:
- Location 2
-- SubLocation 3
-- SubLocation 4
---- SubLocation 5
---- SubLocation 6
所以我的问题是,在关系数据库中存储这种结构的最佳方式是什么?
您可以将parent_id引用FK定义为另一个id为的记录(根的parent_id为null)。
要定义层次结构并在一个查询中检索所有子树,可以定义一个额外的字段路径(VARCHAR)。字段应具有用"_"分隔的ID的完整路径
在您的情况下,SubLocation 5的路径="2_4_5">
要检索SubLocation 4的所有子级,您可以使用
select *
from myTable
where path like '2_4%';
有级别深度限制(事实上是路径的大小),但在大多数情况下应该可以。
在MySQL中处理分层数据很困难。因此,尽管您可能将数据存储在递归表中,但查询数据(通常)并不容易。
如果你有一组固定的层次结构,比如三个(我认为是"城市"、"州"、"国家"),那么你可以为每个实体有一个单独的表。这在元素可能随时间变化的情况下有效,并且特别有用。
或者,也可以使用一个表来展开尺寸标注。因此,"城市"、"州"one_answers"国家"都存储在一行中。这会使数据变平,因此不再对其进行规范化。更新变得乏味。但是,如果数据很少更新,那么这就不是问题。此表单是一个"维度"表单,用于OLAP解决方案。
有一些混合方法,将每个元素以递归形式存储在一个表中。然而,该表也包含到顶部的"完整路径"。例如,在您的上一个示例中:
/location2/sublocation3
/location2/sublocation4
/location2/sublocation4/sublocation5
/location2/sublocation4/sublocation6
这便于查询数据。但这是以维护为代价的。更改诸如sublocation4
之类的内容需要更改许多行。思考触发因素。
如果可以的话,最简单的解决方案是为不同的实体使用不同的表。
您可以将其存储在一个表中,并使用self join
检索子位置。