Лучший способ для редактируемой пользователем сортировки - сохранить id
в 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
Это сделает 5
виджетов для user 1
в следующем порядке: 1, 7, 3, 8, 2
; и 2
виджеты для user 2
в следующем порядке: 3, 2
Вы должны создать UNIQUE
индексов для (user_id, widget_id)
и (user_id, prev_widget_id)
.
Чтобы получить виджеты в заданном порядке, вы можете сделать запрос, например, в 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
Чтобы обновить порядок, вам нужно обновить не более 3
строк (даже если вы переместите весь блок виджетов).
SQL Server
и PostgreSQL 8.4
реализуют эту функцию, используя рекурсивные 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
См. Эту статью в моем блоге о том, как реализовать эту функцию в MySQL
: