在SQL中保存订单首选项

时间:2009-12-07 16:42:35

标签: sql database database-design

我想看看处理以下场景的最佳方法是什么

我有一个叫做用户的表,我有一个名为items的表。每个用户可以将多个项目添加到他的帐户。我有另一个表,比如说AssociateItem,它维护用户和项之间的关联。 (将UserID链接到ItemID)。用户可以拥有多个项目,因此用户和项目之间存在一对多的关系。这些项目的显示顺序很重要,用户可以从UI更改顺序(类似于Netflix队列:)。所以我需要一种方法来保存某个地方的订单,让我们说首选表。所以对于每个用户,我可以保存显示顺序。

我想到了一个用于保存订单的简单XML。假设用户的帐户中有第1,3和5项,显示顺序为3,5,1。我可以维护xml并在每次用户更改其显示首选项时更改它

<order>
<item>3</item>
<item>5</item>
<item>1</item>
<order>

这似乎是一种笨拙的方式。我不是数据库专家。所以,如果有人能提供更好的解决方案。我会非常感激。对不起,如果情景不是很清楚。

6 个答案:

答案 0 :(得分:9)

您可以在AssociateItem表上添加订购号。然后,您可以检索按此订购号订购的商品。

e.g。

TABLE AssociateItem(UserId, ItemId, SortNumber)

SELECT * FROM User U
INNER JOIN AssociateItem AI ON U.UserId = AI.UserID
INNER JOIN Item I ON AI.ItemId = I.ItemId
ORDER BY AI.SortNumber

当您想要移动项目时,杂乱的部分会出现,因为您需要确保数字保持同步。

如果SortNumber是一个整数,那么您需要将以下项目的所有SortNumbers更新为数字+ 1.

您可以作弊并通过使用实数来避免所有这些更新,并在上一个和下一个项目SortNumbers之间的中点对新项目进行排名。

e.g。如果您想在序列0,1,2,3的第2位插入某些内容,则可以为其指定编号为0.5的0, 0.5, 1, 2, 3

如果你想在第2位插入一些新内容,你可以将其指定为0.25给0, 0.25, 0.5, 1, 2, 3等等。显然,当你没有足够的精度来正确表示数字时,这将停止工作但是它应该适用于小型清单。

答案 1 :(得分:2)

两点:

1)要回答您的问题,您可以在关联表中保存订单。添加“OrderNumber”字段以及“userId”和“itemId”。正如您在xml中提到的那样维护该字段。只有少数特定的实例需要在SQL驱动的Web应用程序中维护xml中的数据,而这不是其中之一。将此信息保存在数据库中以保持一致性和速度。

2)这看起来像是多对多的关系而不是一对多。您明确表示一个用户可以拥有多个项目,因此告诉我其中一个选项。剩下的问题是一个项目可以属于许多客户吗?如果是这样,它是多对多的,你需要AssociateItem表。但是,如果每个项目只能属于一个客户端,那么您具有一对多关系,并且您不需要AssociateItem表。而是将userId添加到items表中,并将新的“OrderNumber”字段直接添加到items表中。只是想一想。

答案 2 :(得分:2)

这就是我建模的方式:

CREATE TABLE Application_Users
(
     user_id     INT NOT NULL,  -- Maybe do without this if the user_name is unique
     user_name   VARCHAR(20) NOT NULL,
     ...
     CONSTRAINT PK_Application_Users PRIMARY KEY CLUSTERED (user_id)
)

CREATE TABLE Widgets     -- Items is a really bad table name generally
(
     widget_id     INT NOT NULL,
     widget_name   VARCHAR(20) NOT NULL,
     description   VARCHAR(2000) NOT NULL,
     ...
     CONSTRAINT PK_Widgets PRIMARY KEY CLUSTERED (widget_id)
)

CREATE TABLE User_Widgets
(
     user_id     INT NOT NULL,
     widget_id   INT NOT NULL,
     ranking     SMALLINT NOT NULL,
     CONSTRAINT PK_User_Widgets PRIMARY KEY CLUSTERED (user_id, ranking)
)

User_Widgets上的PK值得商榷。如果他们一次只能在队列中有一个特定小部件的实例,那么理论上你可以将PK打开(user_id,widget_id)。如果他们可以有排名关系,那么你可以将PK放在所有三列上。这取决于业务要求。

如果您确实在PK中包含排名,请记住,它可能会使项目的排名变得更加困难。您通常会通过删除和插入更改而不是更新行来解决问题。例如,要交换等级4和5,您将删除这两行,然后使用更正的排名重新添加项目。我个人认为这不是一件坏事,但你需要牢记这一点。

答案 3 :(得分:0)

我会考虑这两个项目之间的链接表,(我认为)这是一个相当行业标准的方法。

所以你有一个名为“User”的表和一个名为“Items”的表。您将需要创建一个名为“UserItems”的第三个表。

这个新表将拥有自己的主键,但随后包含两个外键;一个到User表,一个到Items表。根据您的要求,您还需要添加一列来存储优先级或序列。

从前端开始,当用户添加项目并为其赋予优先级时,您只需在UserItems表中添加一行。重新分配优先级将更新一行等等。

答案 4 :(得分:0)

在items表中添加一个指定其顺序的列。 BTW,您使用哪个DBMS?

答案 5 :(得分:0)

应该这样做;该订单属于useritem之间的关系。如果某个商品只能属于一个用户,请在ItemID in UserItem上添加其他唯一约束。

itemorder_model_01