我有一个PHP应用程序,它使用MySQL数据库进行对象标记,其中我使用了被接受为this SO question答案的标记结构。
我想实现一个标签层次结构,每个标签可以有一个唯一的父标签。然后,对父标签T的搜索将匹配T的所有后代(即T、父标签是T的标签(T的子标签)、T的孙子标签等)。
最简单的方法似乎是向标签表添加一个ParentID字段,该字段包含标记的父标记的ID,如果标记没有父标记,则添加某个魔术数字。然而,搜索后代则需要对数据库进行重复的全面搜索,以找到每个“代”中的标签,这是我想要避免的。
一种(可能)更快,但更不规范的方法是创建一个表,其中包含每个标记的所有子标记,甚至每个标记的所有子代。然而,这存在数据库中数据不一致的风险(例如,标签是多个父级的子级)。
有没有一种好的方法来进行查询来快速找到后代,同时尽可能地保持数据的规范化?
发布于 2008-11-02 18:24:27
Ali的答案有一个链接到Joe Celko's Trees and Hierarchies in SQL for Smarties,这证实了我的怀疑--没有一个简单的数据库结构可以提供最好的世界。对我来说,最好的似乎是本书中详细描述的“频繁插入树”,它类似于阿里链接的“嵌套集合模型”,但具有非连续的索引。这允许O(1)插入(非结构化基本行编号),并在需要时偶尔重新组织索引。
发布于 2008-11-02 16:15:00
我使用两列实现了它。我在这里稍微简化了一下,因为我必须将标记名保存在单独的字段/表中,因为我必须为不同的语言本地化它:
例如,请看下面的行:
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/等。
使用path字段上的like运算符,您可以轻松获得所有需要的标记行:
SELECT * FROM tags WHERE path LIKE 'database/%'有一些实现细节,比如当你在层次结构中移动一个节点时,你必须改变所有的子节点等等,但这并不难。
还要确保路径的长度足够长-在我的例子中,我使用的不是路径的标记名,而是另一个字段,以确保不会得到太长的路径。
发布于 2008-11-02 16:19:17
https://stackoverflow.com/questions/256997
复制相似问题