【问题标题】:How to add a sort order to a MySQL closure table representing a many-to-many relationship?如何向表示多对多关系的 MySQL 闭包表添加排序顺序?
【发布时间】:2012-03-27 22:04:43
【问题描述】:

这是我的问题的后续:
How to implement a many-to-many hierarchical structure in MySQL
在这里:
How to record sequential collections of records in MySQL.

简而言之,我想在 MySQL 中实现一个食谱表和另一个指令表。配方是一系列连续的指令或其他配方。例如,您可以想象一个Peach_preserve 配方和一个使用Peach_preservePeach_tart,以及一系列其他步骤(说明)。 Peach_preserve 可用于许多其他食谱。

我阅读了this blog post by Bill Karwin about closure tables,我认为这个解决方案最能解决我的挑战(我的层次结构是多对多的,并且步骤是连续的)。所以例如我会:

recipe
id  name
1   Peach preserve
2   Cubed peeled peaches
3   Fresh peaches
4   Powdered sugar
5   Cook together
6   Peel and cut in chunks
7   Mix

step (or instruction)
id  desc
1   Cook together
2   Buy peaches
3   Buy sugar
4   Peel and cut in chunks
5   Mix

recipe_instruction
(Ancestor) (Descendant)
recipe_id  step_id   depth  descendant_is_instruction
3          3         0      0
3          2         1      1
4          4         0      0
4          3         1      1
6          6         0      0
6          4         1      1
2          2         0      0
2          3         1      0
2          2         2      1
2          6         1      0
2          4         2      1
(and so on...)

我不是descendant_is_instruction 标志的粉丝,但我不知道该怎么做。我想我可以用descendant_is_leaf 替换它来识别终端项目...

排序顺序由一个包含深度为 1 的所有关系的表表示:

Depth=1 table
recipe_id  step_id      order
3           2            1
4           3            1
6           4            1
2           3            1
2           6            2

我在这里进行了简化,因为在实践中我会将成分和说明分开,但你明白了。

那么,这是一种结合分层数据结构和步进顺序概念的好方法吗?我应该做些什么来改进/简化?

【问题讨论】:

    标签: mysql hierarchical-data


    【解决方案1】:

    配方是一系列连续的指令或其他配方。

    这取决于人们如何阅读该句子,这可能是模棱两可的。

    怎么样:

    配方是一系列连续的指令。

    一条指令要么是简单的(一片叶子),要么是复杂的(使用另一个配方)。

    这给出了:

    Table recipe:
    - column id
    - column name
    - column total_cost, total_preparation_time, etc
    
    Table instruction:
    - column id
    - column recipe_id
    - column step_order
    - column description
    - column child_recipe_id (can be NULL)
    

    那么,如果桃挞用的是面团和桃子蜜饯:

    select * from recipe order by id;
    id      name
    1       Dough
    2       Peach preserve
    3       Peach tart
    
    select * from instruction order by recipe_id, step_order;
    id recipe_id step_order description     child_recipe_id
    
    100     1       1       Get flour       NULL
    101     1       2       Add water       NULL
    102     1       3       Mix together    NULL
    
    201     2       1       Peel peaches    NULL
    202     2       2       Cube peaches    NULL
    203     2       3       Add sugar       NULL
    204     2       4       Cook together   NULL
    
    301     3       1       Pre heat oven   NULL
    302     3       2       Prepare dough   1
    303     3       3       Prepare peach   2
    304     3       4       Bake            NULL
    

    没有“是叶子”标志。

    如果指令不指向子配方,则它就是叶子,即 child_recipe_id 为 NULL。

    【讨论】:

    • 从这个意义上说,description/name 字段相互之间是多余的。让一张表保存食谱树,另一张只保存名称怎么样?
    • @Yuval,我没有看到配方名称和使用配方的指令描述是多余的。前者描述了生成的成分是“什么”(例如,“融化的巧克力”),后者描述了结果的“如何”使用(例如,“用融化的巧克力在盘子里画艺术”)。嗯。
    【解决方案2】:

    我可能离这里很远,但食谱和指令可以是同一张表,简化你的关系。

    说明:id、name、is_recipe

    步骤:parent_id、child_id、order

    现在一个食谱可以有小时候的说明和食谱。一个指令甚至可以是遵循食谱,但减少黄油......

    您可能需要添加一些循环控制...

    【讨论】:

      【解决方案3】:

      所以我对我的问题进行了一些研究,主要利用了 Bill Karwin 在这里和其他地方提供的信息(我最终决定买他的书)。基于此,我认为最好的选择是在我的关闭表中添加一个面包屑列,类似于比尔在这里推荐的 MySQL Closure Table hierarchical database - How to pull information out in the correct order

      面包屑允许我ORDER BY,这将解决我的订购问题。

      我会通过查询闭包表来找到终端节点,寻找除了自己之外没有祖先的所有节点。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-28
        • 1970-01-01
        • 2016-01-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多