2011-11-01 86 views
4

假设我有两件“我可以卖的东西”:serviceproduct。每个表格都有一个表格,表示它们的独特属性(例如,服务可能有每小时费率,而产品可能有每单位价格等)。针对电子商务的数据库设计问题

每次进行销售时,都假设我需要捕获与销售完全相同的数据,而不管服务或产品是否已售出。我如何建模?

方法1:

  1. 我创建一个表来保存每个销售的细节
  2. 我创建两个“映射”表的产品或服务与销售表
连接

所以,像这样:

TABLE: product 
- product_id (PK) 

TABLE: service 
- service_id (PK) 

TABLE: sale 
- sale_id (PK) 

TABLE: product_sale 
- product_id (FK) 
- sale_id (FK) 

TABLE: service_sale 
- service_id (FK) 
- sale_id (FK) 

方法2:

跳过映射表,只是有单独的表来记录产品和服务的销售情况。

TABLE: product 
- product_id (PK) 

TABLE: service 
- service_id (PK) 

TABLE: product_sale 
- product_sale_id (PK) 
- product_id (FK) 

TABLE: service_sale 
- service_sale_id (PK) 
- service_id (FK) 

我觉得方法1会更好,因为我需要生成像报告:

  • 在一定时期内
  • 每个销售人员的销售总额
  • 总销售额

回答

7

由于您列出的原因,您的方法1比方法2更有利。能够收集所有类型的销售数据并在一次销售中拥有多个物品。方法2表明,产品和服务一次只销售一次,不捆绑在一起。但是我不得不想知道,为什么要首先将产品和服务分开? (根据您的需求,这将是特定行业)。大多数电子商务系统和小型企业会计系统使用一个简单的模型和一个产品表。

因此,这里是我用一个产品表你的问题的官方回答是:

  1. 结构中的[产品]表有PricePerUnit和UnitOfMeasure (可能是小时,可能是每个,可能是,对于标准服务可能是预订率 )。这可以充分描述大多数小公司的产品/服务之间的模型差异定价 。
  2. 现在在您的[product_sale]表(又名“InvoiceLineItem”,以我的 为例)中添加备注字段。在这个领域,你可以写出 有关销售产品/服务的细节。如果是服务, 您可能会输入一些注释供客户参考,如 “执行X服务,调整B部件和抛光C调整 旋钮”。

所以,你必须在这个简单的例子三个表:

  • [产品] - 包含主数据或你的产品和服务,包括他们的定价措施,一些单位“目录”。
  • [发票] - 包含您的销售信息或发票标题包​​括日期,事务ID,也许销售人员等
  • [invoicelineitems] - 在许多一对多风格的产品有两个外键连接的发票。

这是多么现成的电子商务系统和小型企业会计系统的工作原理。

如果您需要超级特定跟踪,那么您肯定会变得更加复杂,但您需要通过解释为什么单位架构的价格不适用于您的用例来证明成本和复杂性。 (汽车经销商就是一个例子,在这个例子中,服务的跟踪与完全不同,服务/产品在单独的表格中都与代表关于汽车的“问题”或“投诉”的订单项相关联。每个订单项都有一个产品组件和一个服务组件。)

更新:看起来我在原始答案中不够清楚,正如@Doug指出的那样。创建销售发票时,当需要转换交易时,将当前PricePerUnit复制到InvoiceLineItem记录以及QuantitySold字段以及对产品主数据的快照非常重要的任何其他数据。这确保发票始终保持相同的总额,即使未来产品价格发生变化。如果客户退货,并且确保客户获得与付款相同的金额,无论当前价格如何,它还允许您撤销发票。

0

我已经做到了以上这样一次:

表产品: - PRODUCT_ID(PK) - 描述 - product_type_id(FK)

表发票:

  • invoice_id
  • client_id

表invoice_line: - INVOICE_ID - PRODUCT_ID - product_type_id - 价格

表PRODUCT_TYPE - product_type_id - 描述

所以,在你的最后一个表,设置两个itens:1 - “产品”, 2 - “服务” 产品将按照“1”,“香蕉”,“1”(这是一种产品)创建。 服务将像这样创建“2”,“换油”,“2”(这是一项服务);

现在,在创建发票时,请确保将所选产品的product_type_id传递到invoice_line表中。这样可以在查询“SELECT * from invoce_line WHERE product_type_id = 2”等数据时获得更高的性能 - 获取销售服务的所有数据。 (1个产品)。

因此,您将所有发票数据都保存在唯一表格中;你可以得到的,例如,所有的客户通过一个简单的服务连接查询像(CLIENT_ID是10):

Select * from invoice_line 
join invoice 
on invoice_line.invoice_id = invoice.invoice_id and client_id = 10 
where product_type_id = 2 

这会做的伎俩几乎一切。我有超过1000人在这样的事情上工作,直到今天,没有任何缺陷。

希望它有帮助。

0

如果您试图规范化数据库,第一种方法是有利的。在这种情况下,对于不同的产品,您可以使用sale实体的属性与sale_id = xx。在第二种情况下,如果您销售的是每个销售的多个产品/服务(销售交易),则需要复制销售的属性。

按人物/日期范围查询可以使用索引策略/分区来解决。如果你知道你的数据会快速增长......所以这将是关于DW项目的另一个问题。

希望它有帮助。

5

事实上,我会做不同的看法:

TABLE: salable 
- salable_id (PK) 
- price (per unit) 
- unit ("hour", "kilogram", "part", "unit") 
- description 

TABLE: product 
- salable_id (FK) 
- manufacturer 
- units_in_stock 

TABLE: service 
- salable_id (FK) 
- provider 

TABLE: sale 
- sale_id (PK) 
- salable_id (FK) 
- units 
- total 

点在于“实用”摘要的东西是共同的服务和产品。这可能不是您的理想解决方案,但它是其他人尚未提及的可行设计。

附录:为确保准确的记录,大多数受尊重的销售/财务系统会为每个销售的每个订单项记录每个产品/服务记录的快照。由于我们应该拍卖我们的产品记录快照无论如何,更容易和更直接的方法是所有可出售的商品共享一组核心领域。

+0

谢谢@svidgen。我其实只是考虑了抽象,而不是实际的影响。 –

+0

我喜欢你的方法,但我会将salable_id,单位和总数从销售移至sale_datails。此外,我会在sales_detail上重复价格,因为价格可能会发生变化,所以每个人都这样做。 – danihp

1

方法1最适合您的目的。它也适用于构建在数据库层之上的中间件层 - 您可以轻松地将ORM解决方案放在现有数据库结构上,并使用第一种方法建模

0

在编写本文时,我相信,答案是忽略一个东西:

当东西的价格变化时会发生什么?

我提起这件事是因为你特别提到了报道。

以前的所有销售是否都显示新价格?是否所有的服务费用都以相同的费率(或者一些客户可以享受折扣?)

我认为您的“销售”的域名概念需要包含纯粹为价值对象的“已售商品”。

这可能不重要 - 但你必须决定这样的事情。这就是为什么领域模型得到很多挥手的原因。

所以我建议选择1,但考虑到产品/服务销售表应该指的是sold_product和sold_service,而不是“原产地”产品/服务。