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

时间:2008-08-21 16:20:13

标签: mysql algorithm data-structures invariants

我有一个在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由某人设置。对于内部节点,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无法更新启动触发器的表格
  • 设置触发器以安排更新任何行的父级的更新
    • 这将是迭代的(从计划中获取项目,处理它计划更多项目)
    • 是什么踢了这个?信任客户端代码以使其正确吗?
    • 一个优点是,如果正确订购更新,则需要的计算机数量更少。但是这种排序是一种并存的复杂因素。

理想的解决方案将推广到其他“聚合不变量”

FWIW我知道这有点“落伍”,但我这样做是为了好玩(乐趣:动词,通过这样做找到不可能的事情。: - )

2 个答案:

答案 0 :(得分:1)

我不确定我是否理解你的问题,但这可能会有效My take on trees in SQL

链接帖描述了在数据库中存储树的方法 - 在这种情况下是PostgreSQL - 但该方法足够清晰,因此可以轻松地用于任何数据库。

使用此方法,您可以轻松更新依赖于已修改节点 K 的所有节点以及 N 简单SELECT查询,其中 N 是距离来自根节点的 K

我希望你的树不是很深:)。

祝你好运!

答案 1 :(得分:1)

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

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

如果您不喜欢这种方法作为答案,我会让您看一下页面using this method in mysql,而不是继续讨论。但如果你喜欢它,发布/编辑,我会花些时间澄清一下。