我有一个在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
的值。可以假设叶节点将保留为叶节点,内部节点将作为内部节点保留,整个事物将保留为正确的树。
我有过一些想法:
理想的解决方案将推广到其他“聚合不变量”
FWIW我知道这有点“落伍”,但我这样做是为了好玩(乐趣:动词,通过这样做找到不可能的事情。: - )
答案 0 :(得分:1)
我不确定我是否理解你的问题,但这可能会有效My take on trees in SQL。
链接帖描述了在数据库中存储树的方法 - 在这种情况下是PostgreSQL - 但该方法足够清晰,因此可以轻松地用于任何数据库。
使用此方法,您可以轻松更新依赖于已修改节点 K 的所有节点以及 N 简单SELECT查询,其中 N 是距离来自根节点的 K 。
我希望你的树不是很深:)。
祝你好运!
答案 1 :(得分:1)
您遇到的问题很明显,SQL中的递归。您需要获取叶子的父级的父级并更新它的总数(减去旧的并添加新的或重新计算)。您需要某种形式的标识符来查看树的结构,并获取所有节点子节点以及要更新的叶子的父节点/路径列表。
此方法添加了常量空间(表中有2列 - 但您只需要一个表,否则以后可以进行连接)。我前段时间使用了一个结构,使用了一个分层格式,使用了“左”和“右”列(显然不是那些名称),分别通过预订遍历和后序遍历计算 - 不用担心这些不需要每次都重新计算。
如果您不喜欢这种方法作为答案,我会让您看一下页面using this method in mysql,而不是继续讨论。但如果你喜欢它,发布/编辑,我会花些时间澄清一下。