The best way for user editable editing is to store id in a linked list :
user_id widget_id prev_widget_id ---- ---- ---- 1 1 0 1 2 8 1 3 7 1 7 1 1 8 3 2 3 0 2 2 3
This will make 5 widgets for user 1 in the following order: 1, 7, 3, 8, 2 ; and 2 for user 2 in the following order: 3, 2
You must make the UNIQUE indexes on (user_id, widget_id) and (user_id, prev_widget_id) .
To get widgets in a given order, you can query, for example, this in Oracle :
SELECT w.* FROM ( SELECT widget_id, level AS widget_order FROM widget_orders START WITH user_id = :myuser AND prev_widget_id = 0 CONNECT BY user_id = PRIOR user_id AND prev_widget_id = PRIOR widget_id ) o JOIN widgets w ON w.widget_id = o.widget_id ORDER BY widget_order
To update the order, you will need to update no more than 3 lines (even if you move the entire block of widgets).
SQL Server and PostgreSQL 8.4 implement this function using recursive CTE s:
WITH -- RECURSIVE -- uncomment the previous line in PostgreSQL q AS ( SELECT widget_id, prev_widget_id, 1 AS widget_order FROM widget_orders WHERE user_id = @user_id UNION ALL SELECT wo.widget_id, wo.prev_widget_id, q.widget_order + 1 FROM q JOIN wo.widget_orders wo ON wo.user_id = @user_id AND wo.prev_widget_id = q.widget_id ) SELECT w.* FROM q JOIN widgets w ON w.widget_id = q.widget_id ORDER BY widget_order
See this blog post on how to implement this functionality in MySQL :