Reputation: 1073
I have a table representing a system of folders and sub-folders with an ordinal m_order
column.
Sometimes sub-folders are sorted alphanumerically, others are sorted by date or by importance.
I recently had to delete some sub-folders of a particular parent folder and add a few new ones. I also had to switch the ordering scheme to alphanumeric. This needed to be reflected in the m_order
column.
Here's an example of the table:
+-----+-----------+-----------+------------+
| 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 |
| ... | ... | ... | ... |
+-----+-----------+-----------+------------+
And here is what I want:
+-----+-----------+-----------+------------+
| 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 |
| ... | ... | ... | ... |
+-----+-----------+-----------+------------+
Upvotes: 2
Views: 529
Reputation: 8725
I needed both t-sql and Oracle versions of this. To save future readers the struggle with the subtle differences in the ORA UPDATE
syntax, here it is, shamelessly ripped off Gordon Linoff's answer:
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;
Upvotes: 0
Reputation: 1270523
I would do this with a simple 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;
This restarts the ordering for each parent. If you have a particular parent in mind, use a WHERE
clause:
where parentid = @parentid and m_order <> toupdate.seqnum
Upvotes: 3
Reputation: 1073
After deleting the old folders and inserting the new records, I accomplished the reordering by using MERGE INTO
and ROW_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
Upvotes: 1