代码之家  ›  专栏  ›  技术社区  ›  BCS

如何在MySQL数据库中维护递归不变量?

  •  2
  • BCS  · 技术社区  · 16 年前

    我在MySQL数据库中有一个树编码为边缘:

    CREATE TABLE items (
        num INT,
        tot INT,
        PRIMARY KEY (num)
        );
    CREATE TABLE tree (
        orig INT,
        term INT
        FOREIGN KEY (orig,term) REFERENCES items (num,num)
        )
    

    对于树上的每一片叶子, items.tot 是由某人设定的。对于内部节点, 项目名称 需要是孩子们的总和。重复运行以下查询将生成所需的结果。

    UPDATE items SET tot = (
        SELECT SUM(b.tot) FROM
            tree JOIN items AS b
            ON tree.term = b.num 
            WHERE tree.orig=items.num)
        WHERE EXISTS 
            (SELECT * FROM tree WHERE orig=items.num)
    

    (请注意,这实际上不起作用,但这不是重点)

    假设数据库存在并且不变量已经满足。

    问题是:

    在维护这个需求的同时,更新数据库的最实用的方法是什么?更新可能会移动节点或更改 tot 在叶节上。可以假定叶节点将保持为叶节点,内部节点将保持为内部节点,整个对象将保持为适当的树。

    我的一些想法:

    • 完全无效,在任何更新之后,重新计算所有内容(嗯…不)
    • 在items表上设置触发器以更新任何已更新行的父级
      • 这将是递归的(更新触发更新、触发更新…)
      • 不起作用,MySQL无法更新启动触发器的表
    • 设置触发器以计划更新任何已更新行的父级
      • 这将是迭代的(从时间表中获取一个项目,处理它来安排更多的项目)
      • 是什么引起的?信任客户端代码以使其正确?
      • 一个优点是,如果更新的顺序正确,那么需要计算机处理的金额就更少了。但这种排序本身就很复杂。

    理想解可以推广到其他“聚集不变量”

    我知道这“有点过火”,但我这样做是为了好玩(有趣:动词,通过这样做发现不可能)。-)

    2 回复  |  直到 14 年前
        1
  •  1
  •   nlucaroni    14 年前

    您遇到的问题很明显,在SQL中是递归的。你需要得到父母的父母…并更新叶的总数(要么减去旧的并添加新的,要么重新计算)。您需要某种形式的标识符来查看树的结构,并获取要更新的叶的所有子节点和父级/路径列表。

    这个方法添加了常量空间(表中有2列——但您只需要一个表,否则您可以稍后进行联接)。我之前玩过一个使用“左”列和“右”列(显然不是那些名称)的层次结构格式的结构,分别由顺序前遍历和顺序后遍历计算——不用担心,这些不需要每次都重新计算。

    我让你看一页 using this method in mysql 如果您不喜欢此方法作为答案,则不要继续此讨论。但如果你喜欢的话,请发表/编辑,我会花些时间澄清。

        2
  •  1
  •   Grzegorz Gierlik    16 年前

    我不确定我是否正确理解你的问题,但这是可行的。 My take on trees in SQL .

    链接后描述的在数据库中存储树的方法——在这种情况下是postgresql——但是该方法足够清晰,因此可以很容易地用于任何数据库。

    使用此方法,您可以轻松地更新所有依赖于修改后节点的节点。 K 关于 n 简单选择查询 n 是距离 K 从根节点。

    我希望你的树不是很深。

    祝你好运!

    推荐文章