如何在没有循环的情况下重新排列分层数据?

Posted

技术标签:

【中文标题】如何在没有循环的情况下重新排列分层数据?【英文标题】:How can I re-rank hierarchical data without a loop? 【发布时间】:2013-03-07 14:42:19 【问题描述】:

我正在尝试重新排列分层数据集中的节点。这是您所期望的结构。一个菜单项将有一个父菜单项,但在这种情况下......我在一个父项下大约有 n 个菜单项。如果我将菜单项从位置 10 移动到位置 5,如下所示:

1 2 3 4 5 6  7 8 9 10 <-- Original
1 2 3 4 5 10 6 7 8 9  <-- New

有没有一种方法可以在一个操作中执行此操作,而不是循环遍历集合并将新位置与现有位置进行比较?我以为我看到了一些可以做到这一点的 RANK 功能,但我似乎找不到它。

更新:它的结构如下:

MENUID, PARENTID, SORT_RANK
1       100       1
2       100       2
3       100       3
4       100       4
5       100       5

如果我将 MENUID 5 向上移动三个位置,它将位于 2 到 3 之间,我想更新排序等级。有没有办法在不获取 parentID 结构并遍历所有记录的情况下做到这一点。

【问题讨论】:

我不确定我是否理解这些数据的层次结构。你能详细说明一下吗? @VincentMalgrat 现在看看... 【参考方案1】:

我想到了两种可能性。

首先是将移动项目的 SORT_RANK 更改为前后项目的平均值,因此如果您想移动 MENUID=5 的项目,使其介于 MENUID 2 和 MENUID 3 之间,您需要设置 SORT_RANK对于 MENUID=5 到 2.5。因此,类似于以下内容:

UPDATE MENU_TABLE
  SET SORT_RANK = ((SELECT SORT_RANK FROM MENU_TABLE WHERE MENUID = 2) + 
                   (SELECT SORT_RANK FROM MENU_TABLE WHERE MENUID = 3)) / 2
  WHERE MENUID = 5;

通过这种方式,您最终会得到具有非整数值的 MENUID,但它们仍然可以正确排序。

第二个是执行以下操作:

UPDATE MENU_TABLE
  SET SORT_RANK = SORT_RANK + 1
  WHERE PARENTID = 100 AND
        SORT_RANK > 2;

UPDATE MENU_TABLE
  SET SORT_RANK = 3
  WHERE MENUID = 5;

但是,后一种方法需要两个语句,这可能不是您想要的。

分享和享受。

【讨论】:

【参考方案2】:

我不确定数据按层次结构构造这一事实是否重要。

您可以通过一个查询来更新您的订单。假设 rank_order :R_START 的项目到 :R_STOP 的地方:

SQL> variable r_start NUMBER
SQL> variable r_stop NUMBER
SQL> EXEC :r_start := 5; :r_stop := 3;

PL/SQL procedure successfully completed

SQL> UPDATE mytable
  2     SET sort_rank = CASE WHEN sort_rank = :R_START  THEN :R_STOP
  3                      ELSE sort_rank + sign(:R_START - :R_STOP)
  4                      END
  5   WHERE parentid = 100
  6     AND sort_rank BETWEEN LEAST(:R_START, :R_STOP)
  7                       AND GREATEST(:R_START, :R_STOP);

3 rows updated

SQL> select * from mytable order by sort_rank;

    MENUID   PARENTID  SORT_RANK
---------- ---------- ----------
         1        100          1
         2        100          2
         5        100          3
         3        100          4
         4        100          5

【讨论】:

【参考方案3】:

我会用一个问题来回答你的问题;你为什么要求你的SORT_RANK 字段由整数组成?

如果SORT_RANK 字段只是NUMBER,而不是NUMBER(10,0),您可以将任何项目移动到任何位置,而不会出现重新排名问题。

【讨论】:

以上是关于如何在没有循环的情况下重新排列分层数据?的主要内容,如果未能解决你的问题,请参考以下文章

如何重新排列javascript循环中的数字?

如何在没有顺序重复的情况下获得 PHP 中的所有排列?

在没有 for 循环的情况下应用用户定义的函数

React Native - 如何在没有完全重新渲染的情况下在 ListView 中添加和附加数据

TypeError:“sqlite3.Cursor”对象不可下标。如何在没有for循环的情况下打印sql选择数据[重复]

如何修复 ImportError:尝试在没有已知父包的情况下进行相对导入