用户可排序的记录

时间:2009-08-23 22:21:23

标签: database database-design

对于我的webapp中的每个用户,都有n个相关的小部件。每个窗口小部件都在数据库的Widgets表中表示。用户可以对他们的小部件进行排序,他们永远不会有超过几十个小部件,他们会经常对小部件进行排序。

我没有经常处理过具有固有顺序的数据库项目。订购它们的好策略是什么?起初,我认为一个简单的“sortIndex”列可以正常工作,但后来我开始想知道如何初始化这个值。它可能必须是一个唯一的值,它应该大于或小于每个其他排序索引。但是,每次创建新窗口小部件时,我都不想检查该用户的所有其他排序索引。这似乎没必要。

也许我可以使用默认的“底部优先级”排序索引?但那我该如何区分呢?我想我可以使用创建日期标志,但是如果用户想要在所有这些底部优先级小部件的中间插入一个小部件会怎么样?

处理此类事情的标准方法是什么?

4 个答案:

答案 0 :(得分:4)

如果您有用户为自己的个人品味排序小部件,您需要创建一个查找表,如下所示:

create table widgets_sorting
(
    SortID int primary key,
    UserID int,
    WidgetID int,
    SortIndex int
)

然后,对用户的小部件进行排序:

select
    w.*
from
    widgets w
    inner join widgets_sorting s on
        w.WidgetID = s.WidgetID
    inner join users u on
        s.UserID = u.UserID
order by
    s.SortIndex asc

这样,您只需为新用户执行操作即可向widgets_sorting表添加新行。确保在WidgetID和UserID列上都放置了外键约束和索引。

这些查找表实际上是解决这种个性化列表中常见的多对多关系的最佳方法。希望这能指出你正确的方向!

答案 1 :(得分:3)

用户可编辑排序的最佳方法是将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的{​​{1}}个小部件:user 2

您应该在3, 2UNIQUE上制作(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 行(即使您移动整个小部件块)。

3SQL Server使用递归PostgreSQL 8.4来实现此功能:

CTE

在我的博客中查看有关如何在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 中实现此功能的文章:

答案 2 :(得分:1)

我喜欢使用双表方法 - 这可能有点令人困惑但是如果你使用像ActiveRecord这样的ORM它很容易,如果你编写一些聪明的代码就可以管理它。

使用一个表将用户链接到排序,使用一个表链接小部件和位置以及排序。通过这种方式,可以清楚地了解正在发生的事情,并且可以使用SQL连接或单独的查询从各种表中提取各种数据。您的结构应如下所示:

//Standard user + widgets table, make sure they both have unique IDs
CREATE TABLE users;
CREATE TABLE widgets;

//The sorting tables
CREATE TABLE sortings (
    id INT, //autoincrement etc,
    user_id INT
)

CREATE TABLE sorting_positions (
    sorting_id INT,
    widget_id INT,
    position INT
)

希望这是有道理的,如果你仍然感到困惑,请对此消息发表评论,我会给你写一些基本代码。

杰米

答案 3 :(得分:1)

如果您的意思是每个用户都将自己的排序顺序分配给小部件,那么Eric的答案是正确的。大概你必须给用户一个分配排序值的方法。但是,如果你说的数字是适度的,那么你可以给他一个列出所有小部件的屏幕,然后让他输入订单号,或者按顺序显示它们,并在每个旁边放置按钮,如果你想要花哨,给他一个拖拉的方法。

如果所有用户的订单都相同,那么问题就出现了,这个订单来自哪里?如果它是任意的,只需在创建新小部件时分配序列号。