数据库:订单属性的新表或新字段

Posted

技术标签:

【中文标题】数据库:订单属性的新表或新字段【英文标题】:Database: new table or new field for order attributes 【发布时间】:2020-05-14 10:08:47 【问题描述】:

当前表架构:

User
  - id
  - default_handling_fee(integer, null=True)

Order
  - id
  - buyer(user_id)
  - order_handling_fee(integer, null=True) 

我们现在要添加可应用于订单的第二种费用。一些规则:

    费用适用于 一个订单可以有 0 项费用,也可以是其中一项费用,也可以是两项费用。 每次向用户显示订单信息时,我们需要 突出显示费用并显示费用类型。 费用必须可按订单进行编辑。 今后我们可能会增加额外费用。 数据库目前非常小(几千行),不太可能 在未来几年内增长到 10 万以上。

我可以看到两个选项:

A:在订单上添加一个新字段,在用户上添加一个:

User
  - id
  - default_handling_fee(integer, null=True)
  - default_processing_fee(integer, null=True)

Order
  - id
  - buyer(user_id)
  - order_handling_fee(integer, null=True) 
  - order_processing_fee(integer, null=True)

或 B,添加新的“费用表”:

User
  - id

Order
  - id
  - buyer(user_id)
  - order_fees(many_to_many_field to OrderFees)

OrderFees
  - id
  - buyer(user_id)
  - price(integer)
  - fee_type(choices=['handling', 'processing'])
  - is_default_value(boolean)

如果用户创建订单并应用其中一项或两项费用,在选项 B(新表)中,我们将首先查找与用户和价格相匹配的现有费用。如果该组合存在,我们会将其添加到order_fees 字段。如果它不存在(新价格),我们将创建一个新行并将该行添加到 order_fees 字段。

我认识到选项 A 要简单得多:查找费用时不进行联接,不创建新行,不创建一次就不再使用的陈旧行。 我看到 A 的两个缺点。一方面,它不可扩展。如果我们在几个月后添加gift_wrapping_fee,这将意味着几乎在每个订单上都添加第三个字段为空,以此类推,以获取额外类型的订单费用。第二个缺点是我们必须记住在显示订单信息的每个地方都在应用内添加支票。

if order.order_processing_fee: 
  show fee
if order.order_handling_fee:
  show fee

选择B,就是

for fee in order.order_fees:
  show fee

选项 B 中出错的可能性要小得多,代价是向用户显示的每个订单至少有一个额外的查询。

另外一点:由于这一切都是使用 Django 作为后端完成的,我们可以在模型上定义方法,以便在一个地方定义所有价格字段。

哪个选项更好?有没有我没有考虑过的第三种选择?

(为清楚起见进行了编辑)

【问题讨论】:

第二个违反规范化。不要将order_fees 放入order。但是有另一个表,其中订单的 ID 是外键,它将实际费用存储在引用订单的行中。也就是说,只需支付两笔费用,订单表中的两列可能是可行的解决方案。 【参考方案1】:

我认为,如果在不久的将来,您需要添加新的费用类型,那么 B 选项会更好。

您是否考虑过 A 和 B 的混合选项?如果我理解了这个问题,那么您不仅有订单费,而且还有用户的默认费用。

你可以有一个费用表:

Fees
-id
-type(choices=[your fee type list])
-price
...(other attributes)

然后你可以有两个多对多关系,一个用于订单

Order 
-id
-buyer(user)
-order_fees(many to many)

给用户一秒钟

User
-id
-default_fees(many to many)

【讨论】:

这是一个有趣的混合想法。例如,对于user.default_fees 设计,当用户更改其默认处理费价格时,我们必须在当前default_fees 字段中检查处理费并删除它(如果存在),然后再添加新创建的费用。这不是一项可怕的任务,但它是另一层管理。 hmm...那么您可以添加新的处理费并更改费用和用户之间的关系。也许费用表中的标志(例如活动/非活动)会有所帮助,添加它可以为用户提供费用历史记录。

以上是关于数据库:订单属性的新表或新字段的主要内容,如果未能解决你的问题,请参考以下文章

1 对 1 关系的性能更好:新表或 VARCHAR 列有很多空条目

CSV 文件到 Lua 表并作为新表或函数访问这些行()

text 新表或列

为啥 Pentaho 数据集成无法读取表上的新字段?

如何确定一个想法是不是应该被视为关系数据库中的表或属性?

mysql 优化表或新建一个