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

如何在MySQL数据库中维护递归不变量?,mysql,algorithm,data-structures,invariants,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需要是其

我在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我知道这“有点过火”,但我这样做是为了好玩(好玩:动词,通过这样做来发现不可能的事情。:-

我不确定我是否正确理解了你的问题,但这可能会奏效

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

使用此方法,您可以轻松地更新所有依赖于修改节点K的节点,其中N是距离根节点K的距离

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


祝你好运

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

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


我会让你看一页,而不是继续讨论,以防你不喜欢这个方法作为答案。但是如果你喜欢,发布/编辑,我会花一些时间澄清。

一个有趣的方法。我不喜欢它的一点是它使用了类似于
N*Log(N)
空间的东西。此外,我还有一些版本控制约束,这些约束需要主要的mod遗憾的是,作者从未接触过如何更新聚合值。我可以想出一些方法,但它们将取决于实施情况我得好好考虑一下。(从[very old]答案中删除)我更新了mysql文档中提到该格式的链接。