当前位置: 首页 > 面试题库 >

在嵌套集中移动节点

卢鸿彩
2023-03-14
问题内容

我需要一个MySQL查询,该查询可在一个嵌套集中移动一个节点及其所有子节点。我找到了这个站点,但是该函数似乎非常不合逻辑-
没有universeid或没有treeid嵌套的集合模型,并且代码本身仅比所需的更长。我在表格中仅有的额外一列是parent

我不能只删除并再次添加该节点,因为它将丢失其ID。


问题答案:

我知道,这个主题已经很老了,但是无论如何仍然没有答案。我是从Google来到这里的,没有找到这个问题的直接答案。

因此,经过一些研究,我发现了很简单的解决方案。

一切,我们需要移动节点的是:节点左右位置,新父节点右边位置。然后可以通过四个简单步骤将节点移动到新位置:

  1. 将节点及其所有子节点的位置更改为负值,该值等于模块中的当前值。
  2. 将所有位置“向上”移动,更多,即当前节点的pos_right。
  3. 将所有位置“向下”移动更多,即新父节点的pos_right。
  4. 更改当前节点及其所有子节点的位置,以使它现在恰好在新父节点的“之后”(或“向下”)。

这是理论,现在-这种算法在MySQL中的实现(使用PHP的示例):

-- step 0: Initialize parameters.
SELECT
    @node_id := 1, --put there id of moving node 
    @node_pos_left := 0, --put there left position of moving node
    @node_pos_right := 1, --put there right position of moving node
    @parent_id := 2, --put there id of new parent node (there moving node should be moved)

    @parent_pos_right := 4; --put there right position of new parent node (there moving node should be moved)
SELECT
    @node_size := @node_pos_right - @node_pos_left + 1; -- 'size' of moving node (including all it's sub nodes)

-- step 1: temporary "remove" moving node

UPDATE `list_items`
SET `pos_left` = 0-(`pos_left`), `pos_right` = 0-(`pos_right`)
WHERE `pos_left` >= @node_pos_left AND `pos_right` <= @node_pos_right;

-- step 2: decrease left and/or right position values of currently 'lower' items (and parents)

UPDATE `list_items`
SET `pos_left` = `pos_left` - @node_size
WHERE `pos_left` > @node_pos_right;
UPDATE `list_items`
SET `pos_right` = `pos_right` - @node_size
WHERE `pos_right` > @node_pos_right;

-- step 3: increase left and/or right position values of future 'lower' items (and parents)

UPDATE `list_items`
SET `pos_left` = `pos_left` + @node_size
WHERE `pos_left` >= IF(@parent_pos_right > @node_pos_right, @parent_pos_right - @node_size, @parent_pos_right);
UPDATE `list_items`
SET `pos_right` = `pos_right` + @node_size
WHERE `pos_right` >= IF(@parent_pos_right > @node_pos_right, @parent_pos_right - @node_size, @parent_pos_right);

-- step 4: move node (ant it's subnodes) and update it's parent item id

UPDATE `list_items`
SET
    `pos_left` = 0-(`pos_left`)+IF(@parent_pos_right > @node_pos_right, @parent_pos_right - @node_pos_right - 1, @parent_pos_right - @node_pos_right - 1 + @node_size),
    `pos_right` = 0-(`pos_right`)+IF(@parent_pos_right > @node_pos_right, @parent_pos_right - @node_pos_right - 1, @parent_pos_right - @node_pos_right - 1 + @node_size)
WHERE `pos_left` <= 0-@node_pos_left AND `pos_right` >= 0-@node_pos_right;
UPDATE `list_items`
SET `parent_item_id` = @parent_id
WHERE `item_id` = @node_id;

请注意-SQL代码中仍然可能存在一些语法错误,因为我实际上是在PHP中使用这种算法,如下所示:

$iItemId = 1;
$iItemPosLeft = 0;
$iItemPosRight = 1;
$iParentId = 2;
$iParentPosRight = 4;
$iSize = $iPosRight - $iPosLeft + 1;
$sql = array(

    // step 1: temporary "remove" moving node

    'UPDATE `list_items`
    SET `pos_left` = 0-(`pos_left`), `pos_right` = 0-(`pos_right`)
    WHERE `pos_left` >= "'.$iItemPosLeft.'" AND `pos_right` <= "'.$iItemPosRight.'"',

    // step 2: decrease left and/or right position values of currently 'lower' items (and parents)

    'UPDATE `list_items`
    SET `pos_left` = `pos_left` - '.$iSize.'
    WHERE `pos_left` > "'.$iItemPosRight.'"',
    'UPDATE `list_items`
    SET `pos_right` = `pos_right` - '.$iSize.'
    WHERE `pos_right` > "'.$iItemPosRight.'"',

    // step 3: increase left and/or right position values of future 'lower' items (and parents)

    'UPDATE `list_items`
    SET `pos_left` = `pos_left` + '.$iSize.'
    WHERE `pos_left` >= "'.($iParentPosRight > $iItemPosRight ? $iParentPosRight - $iSize : $iParentPosRight).'"',
    'UPDATE `list_items`
    SET `pos_right` = `pos_right` + '.$iSize.'
    WHERE `pos_right` >= "'.($iParentPosRight > $iItemPosRight ? $iParentPosRight - $iSize : $iParentPosRight).'"',

    // step 4: move node (ant it's subnodes) and update it's parent item id

    'UPDATE `list_items`
    SET
        `pos_left` = 0-(`pos_left`)+'.($iParentPosRight > $iItemPosRight ? $iParentPosRight - $iItemPosRight - 1 : $iParentPosRight - $iItemPosRight - 1 + $iSize).',
        `pos_right` = 0-(`pos_right`)+'.($iParentPosRight > $iItemPosRight ? $iParentPosRight - $iItemPosRight - 1 : $iParentPosRight - $iItemPosRight - 1 + $iSize).'
    WHERE `pos_left` <= "'.(0-$iItemPosLeft).'" AND i.`pos_right` >= "'.(0-$iItemPosRight).'"',
    'UPDATE `list_items`
    SET `parent_item_id` = "'.$iParentItemId.'"
    WHERE `item_id`="'.$iItemId.'"'
);

foreach($sql as $sqlQuery){
    mysql_query($sqlQuery);
}

还请注意,代码可能已经过优化,但是为了更好的可读性,我将其保留下来。如果在多用户系统中使用嵌套集,还应考虑使用表锁定。

希望我的信息能对任何寻求我解决方案的人有所帮助。也欢迎任何评论和更正。



 类似资料:
  • 我想用XSLT转换XML文档。按名称和属性匹配的节点及其子节点应嵌套/移动到新节点中。 从转变 到 但是我的XSLT工作不好。您有什么提示吗,XSLT文件有什么问题? 非常感谢你 安德烈亚斯 我的XSLT 输出: 我的源XML文件 我希望在转换后的输出中将v:data节点及其子节点嵌套到一个新节点中。但只有属性名为“Custon”的v:data节点。转换后的XML文档应该如下所示 如果我从XSLT

  • 问题内容: 我使用以下各列来运行磨机嵌套集层次结构类型设置: 表名: 列: 有谁知道查询以确定节点的 父级 ? 我读了几个地方,在表中也有一个 parent_id 列来跟踪它很方便,但是它看起来很多余,而且如果添加/时查询执行不正确,它似乎可能与嵌套集不同步删除/移动集合中的任何内容。 问题答案: 看这个问题。它与您的相似。我在那里发布了您可能需要的查询。 希望您有需要。 对于下表: 它产生输出:

  • 如何聚合一个值在嵌套在Elasticsearch嵌套位置?我对一个嵌套对象没有问题,但在嵌套对象内的嵌套我感到困惑... 样本数据: 欲望结果: 在索引映射中,我将cat_a和条目字段的类型设置为嵌套,当我从工具字段查询聚合时,在cat_a的根(级别1)中没有问题,并且可以工作,但是在聚合中在rx_a(这是在第2级)我不能检索结果,它或空或显示错误,因为我的错误查询。 查询级别1 agg: 如何处

  • 嗨,我正在尝试在我的 https://www.graph.cool/ db 上写入带有突变的数据。我的项目是一个 React Web 应用程序,我使用 Apollo 作为 graphql 客户端和 graphql-tag npm 包作为模板文字解析器。 问题是我不知道如何使用嵌套数据为正确的突变排列 gql 模板字符串。我的架构如下所示,例如请注意,类型“公司”的字段“地址”是“地址”对象类型的数

  • 我没有发现答案有什么帮助:作为作者,我想要绘制这样的图: 答案是在RDF中必须考虑三元组,但在这里不是这样吗? (地址,有街道,...) (地址,有邮政编码,...) (Person,has address,...) 我问的另一个原因是,我使用Jena Bean从Java类模型中生成RDF,结果也是一个嵌套结构。现在我想用Apache Jena做同样的事情,但我无法找到答案,文档中没有任何提示,我

  • 我创建了嵌套的线性布局,其中包含子按钮和其他线性布局,并将wrap_内容和animateLayoutChanges设置为true。 代码如下 当我从嵌套的LinearLayout中移除按钮时,动画会播放移除按钮的过程,然后再次重复,在整个嵌套布局中创建跳跃效果。 这似乎是API 19和API 25中出现的错误-可能还有其他错误(尚未测试),但它在API上运行良好 问题是,我希望它适用于所有API