Database design 基于项目可用性的多对多树的最佳数据库数据结构

Database design 基于项目可用性的多对多树的最佳数据库数据结构,database-design,tree,hierarchical-data,Database Design,Tree,Hierarchical Data,我目前正在开发一个基于MySQL的网站,但是如果有必要的话,切换到另一个数据库并不是问题,比如CTE之类的 我正在寻找最好的数据库数据结构,如果可能的话,寻找一些SQL代码片段来处理我当前的项目,如下所示: 一个产品可以递归地由其他产品组成,因此产品必须在面向树的体系结构中设计。 一种产品可用于制造许多产品。这就是嵌套集体系结构不起作用的地方,因为一个节点可以是多个节点的子节点和父节点,而使用嵌套集似乎是不可能的。 一种产品每天都有一个数量,但只有当它是一片叶子时,它才不是由另一种产品制成的。否

我目前正在开发一个基于MySQL的网站,但是如果有必要的话,切换到另一个数据库并不是问题,比如CTE之类的

我正在寻找最好的数据库数据结构,如果可能的话,寻找一些SQL代码片段来处理我当前的项目,如下所示:

一个产品可以递归地由其他产品组成,因此产品必须在面向树的体系结构中设计。 一种产品可用于制造许多产品。这就是嵌套集体系结构不起作用的地方,因为一个节点可以是多个节点的子节点和父节点,而使用嵌套集似乎是不可能的。 一种产品每天都有一个数量,但只有当它是一片叶子时,它才不是由另一种产品制成的。否则,它的数量将取决于它的直接子对象的数量,依此类推,直到递归到达叶子。因此,产品可能会链接到一个表availability,其中包含产品id、日期和数量。 产品的树结构非常稳定,因此更新/插入/删除查询的速度并不重要

最终目标是能够在SELECT查询中尽快检索指定两个日期之间可用的所有产品的列表

这意味着:

1如果产品不是由另一种材料制成,则在两个日期之间每天的数量大于0时,该产品可用。 2如果该产品由其他产品制成,则仅当1对其所有子产品均为真时,该产品才可用。如果直接子对象不是叶,则它们将没有数量,因此将发生2的递归,直到它到达最终叶。
顺便说一句,在实际情况下,我的产品的深度永远不会超过5级。将所有父ID存储在单独的列中可能是一个好主意,但非常糟糕。

您描述的数据结构不是一个要求每个节点只有一个父节点的结构,除了根节点没有父节点:相反,它是一个更通用的:

其他RDBMS本机支持分层数据和递归查询,而MySQL则不支持;相反,在MySQL中存储此类数据的一个好的通用关系模型是创建一个图形数据表。使用//作为语句分隔符:

创建表格产品 SKU序列注释“库存单位代码”, 名称VARCHAR15注释“产品名称”, Description VARCHAR255注释“描述性文本”, 价格小数点6,2注释“售价”, isAtomic BOOLEAN默认错误注释“表示原子性的标志” 引擎=InnoDB, 注释='与每个产品相关的属性' // 创建表ProductComponents SKU BIGINT未签名非空注释“库存单位代码”, ComponentSKU BIGINT未签名非空注释“组成组件的SKU”, 主键SKU、组件SKU、, 索引组件SKU,SKU, 外键SKU参考产品SKU, 外键组件SKU参考产品SKU 引擎=InnoDB, 注释='产品DAG的传递闭包' // 可以在后一个表中使用强制原子性:

在ProductComponents上插入之前创建触发器ins_原子 对于每行,如果 NEW.SKU NEW.ComponentSKU 并从SKU=NEW.SKU的产品中选择isAtomic 然后 信号状态“45000”设置 MESSAGE_TEXT='原子产品不能有组件' ; 如果结束// 在更新ProductComponents之前创建触发器upd_原子 对于每行,如果 NEW.SKU NEW.ComponentSKU 并从SKU=NEW.SKU的产品中选择isAtomic 然后 信号状态“45000”设置 MESSAGE_TEXT='原子产品不能有组件' ; 如果结束// 您可能还需要一个类似的触发器来防止产品的错误更新。isAtomic:

在产品更新之前创建触发器upd_产品 如果NEW.isAtomic和存在,则为每行 从ProductComponents中选择*,其中SKU ComponentSKU和SKU=NEW.SKU 然后 信号状态“45000”设置 MESSAGE_TEXT='原子产品不能有组件' ; 如果结束// 对于上述图表,您的数据如下所示:

插入到产品中 单原子 价值观 2,对, 3,错,, 5,错,, 7,错,, 8,错,, 9,对, 10,对, 11,错 // 插入到ProductComponents中 SKU,组件SKU 价值观 2,2, 3,3, 3,8, 3,9, 3,10, 5,5, 5,11, 5,2, 5,9, 5,10, 7,7, 7,8, 7,9, 7,11, 7,2, 7,10, 8,8, 8,9, 9,9, 10,10, 11,11, 11,2, 11,9, 11,10 // 然后,您可以按如下方式存储可用性:

创建表ProductAvailability SKU BIGINT未签名非空注释“库存单位代码”, 日期注释“可用日期”, 数量INT注释“可用数量”, 主键SKU,日期, 外键SKU参考产品SKU 引擎=InnoDB, 注释='可用数量' // 上述的一些测试数据可能是:

插入到ProductAvailability中 SKU、日期、数量 价值观 2,'2012-12-13',无效, 2, '2012-12-15', 15, 9, '2012-12-13', 234, 9, '2012-12-14', 46, 9, '2012-12-15', 0, 10, '2012-12-13', 4, 10, '2012-12-14', 7, 10, '2012-12-15', 5 // 你的问题是:

选择p* 来自产品p 使用SKU连接ProductC组件 参加 选择p.SKU作为组件SKU, 计数*=DATEDIFF@end_date,@start_date+1(如果可用) 从产品p向左加入产品可用性a 在a.SKU=p.SKU上 a.数量>0 a.开始日期和结束日期之间的日期 其中p.isAtomic 按p.SKU分组 q使用组件SKU 按p.SKU分组 没有SUMq.available=0
查看它。

一个法语单词,意思是数据库管理系统,我编辑了我的帖子来翻译它,以为它是一个英语单词。因此,数量不是产品的属性,它是产品和日期的组合属性,对吗?是的,有一个单独的表可用性,它包含三个字段:日期、产品id和数量。我编辑了我的文章。一个产品只有在两个日期之间才可用,如果它在这段时间内的每个日期都可用-对吗?换言之,如果在某个时间间隔内有一天产品不可用,则查询不会返回该产品,从而认为该产品在整个时间间隔内不可用?是间隔吗?是的,只有在每天都有产品可用的情况下,产品才会在日期a和D之间可用,例如:a、B、C、D。本例中包括了a和D。通过您共享的链接,我可以看到,使用MySql、connect by或recursive以外的任何工具都可以轻松处理该图。这可能是处理我所说的树的一个很好的起点,但可用性部分仍然存在。这看起来很完美。非常感谢你的帮助。有空的时候我会给你赏金。