我有一个使用了对象标记技术,在我使用接受的答案this SO question标签结构MySQL数据库PHP的Web应用程序。
我想实现一个标签层次结构,其中每个标签都有一个唯一的父标签。然后父标签T搜索将匹配的T所有后代(即T,标签卫生组织父为T在T(儿童),T的孙子,等)。
这样做的最简单的方法似乎是一个PARENTID字段添加到标签表,其中包含一个标签的父标签的ID,或一些神奇的数字,如果标签没有父。搜索后代,然而,则需要对数据库的重复全搜索找到这些标签,每个“一代”,我想避免。
这样做的(大概)快,但不太标准化的方法是有一个包含每个标签的所有孩子,甚至每个标签的所有后代的表。然而,这运行不一致的数据在数据库中的风险(例如一个标签为一个以上的父母的孩子)。
有没有进行查询,以快速找到子孙的好办法,同时保持数据的标准化越好?
我实现它使用两列。我在这里把它简化一点,因为我必须保持标记名称在一个单独的字段/表,因为我不得不本地化它为不同的语言:
看看这些行,例如:
tag path
--- ----
database database/
mysql database/mysql/
mysql4 database/mysql/mysql4/
mysql4-1 database/mysql/mysql4-1/
oracle database/oracle/
sqlserver database/sqlserver/
sqlserver2005 database/sqlserver/sqlserver2005/
sqlserver2005 database/sqlserver/sqlserver2008/
等等
路径字段使用like
运营商可以很容易地得到所有需要的标签行:
SELECT * FROM tags WHERE path LIKE 'database/%'
还有当你在层次中移动节点像一些实施细节,你必须改变所有的孩子太等,但它并不难。
另外,还要确保您的路径的长度足够长 - 在我的情况下,我不使用标签名称为路径,但另一场以确保我不要太长的路径。
阿里的答案有一个链接到Joe Celko's Trees and Hierarchies in SQL for Smarties,这证实了我的怀疑 - 没有,它提供了世界上最好的一个简单的数据库结构。最适合我的目的似乎是“频繁插入树”在这本书中详细说明,这是像阿里的链接的“嵌套集模型”,但有非连续的索引。这允许O(1)的插入(一拉非结构化BASIC行号),偶尔索引重组作为并在需要时。
你可以建立什么金博尔调用层次助手表。
假设你的层次结构是这样的:A - > C |乙 - > C ^ | Ç - > d
你想插入记录,看起来像这样的表
ParentID, ChildID, Depth, Highest Flag, Lowest Flag
A, A, 0, Y, N
A, B, 1, N, N
A, C, 2, N, N
A, D, 3, N, Y
B, B, 0, N, N
B, C, 1, N, N
B, D, 2, N, Y
C, C, 0, N, N
C, D, 1, N, Y
D, D, 0. N, Y
我想我有一个正确的....反正。问题的关键是你还是你保存正确的层次结构中,你刚刚建立这个表格从你的正确的表。此表查询像一个女妖。假设你想知道什么都低于B中的第一级是。
WHERE parentID = 'B' and Depth = 1
我会用某种形式的阵列来存储儿童标签的,这应该是比自己加入一个表(特别是如果你有大量的标签)快很多。我一看,我不能告诉我们,如果MySQL有一个本地数组数据类型,但是你可以通过使用文本列和存储它的序列化阵列模拟此。如果您想进一步加快速度,你应该能够把一个文本搜索索引该列找出哪些标签是相关的。
[编辑]阅读阿里的文章后,我做了一些更打猎时发现this呈现在一堆在Postgres的实现层次方法。可能仍然是为了便于说明很有帮助。