根据另一列的字母顺序更新序数列

时间:2016-01-20 19:14:03

标签: sql

我有一个表格,其中包含序号为m_order列的文件夹和子文件夹系统。

有时子文件夹按字母顺序排序,其他子文件按日期或重要性排序。

我最近不得不删除某个特定父文件夹的子文件夹并添加一些新文件夹。我还必须将订购方案切换为字母数字。这需要反映在m_order列中。

这是表格的一个例子:

+-----+-----------+-----------+------------+
| ID  | parent    |   title   | m_order    |
+-----+-----------+-----------+------------+
| 100 | 1         | docs      | 3          |
| 101 | 1         | reports   | 2          |
| 102 | 1         | travel    | 1          |
| 103 | 1         | weekly    | 4          |
| 104 | 1         | briefings | 5          |
| ... | ...       | ...       | ...        |
+-----+-----------+-----------+------------+

这就是我想要的:

+-----+-----------+-----------+------------+
| ID  | parent    |   title   | m_order    |
+-----+-----------+-----------+------------+
| 100 | 1         | docs      | 3          |
| 101 | 1         | reports   | 4          |
| 102 | 1         | travel    | 5          |
| 200 | 1         | contacts  | 2          |
| 201 | 1         | admin     | 1          |
| ... | ...       | ...       | ...        |
+-----+-----------+-----------+------------+

3 个答案:

答案 0 :(得分:3)

我会用一个简单的update

来做到这一点
with toupdate as (
      select m.*, row_number() over (partition by parent order by title) as seqnum
      from menu m
     )
update toupdate
    set m_order = toupdate.seqnum;

这会重新启动每个父级的排序。如果您有特定的父母,请使用WHERE子句:

where parentid = @parentid and m_order <> toupdate.seqnum

答案 1 :(得分:1)

删除旧文件夹并插入新记录后,我使用MERGE INTOROW_NUMBER()完成了重新排序:

DECLARE @parentID INT
...

MERGE INTO menu
USING (
        SELECT ROW_NUMBER() OVER (ORDER BY title) AS rowNumber, ID
        FROM menu
        WHERE parent = @parentID
      ) AS reordered
ON menu.ID = reordered.ID
WHEN MATCHED THEN
    UPDATE
    SET menu.m_order = reordered.rowNumber

答案 2 :(得分:0)

我需要t-sql和Oracle版本。为了拯救未来的读者,与ORA UPDATE语法中的细微差别的斗争,在这里,无耻地撕掉戈登·林诺夫的答案:

update (
    with toupdate as (
        select 
            m.primarykey,
            row_number() over(partition by parent order by title) as seqnum
        from menu m
    )
    select m.primarykey, t.seqnum from menu m inner join toupdate t on t.primarykey=m.primarykey
)
set m_order = t.seqnum;