【问题标题】:DB Design Questions for eCommerce电子商务的数据库设计问题
【发布时间】:2011-11-01 04:03:05
【问题描述】:

假设我有 2 个“东西”可以出售: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 会更好,因为我需要生成如下报告:

  • 给定时期的总销售额
  • 每位销售人员的总销售额

【问题讨论】:

    标签: mysql database database-design


    【解决方案1】:

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

    所以这是我使用一张产品表对您的问题的官方回答:

    1. 将 [product] 表构造为具有 PricePerUnit 和 UnitOfMeasure (可能是小时,可能是每个,可能是pairs,可能是book rate 用于标准服务)。这可以充分描述定价 大多数小公司的产品/服务之间的模型差异。
    2. 现在在您的 [product_sale] 表中(在我的 lingo),添加注释字段。在这个领域你可以写 有关所售产品/服务的详细信息。在服务的情况下, 您可以输入一些注释供客户参考,例如 “执行 X 服务,调整 B 小部件并打磨 C 调优 旋钮”。

    所以在这个简单的例子中你有三个表:

    • [产品] - 包含主数据或您的产品和服务“目录”,包括某些计量单位的定价。
    • [invoices] - 包含您的销售信息或发票标题,包括日期、交易 ID、可能是销售人员等。
    • [invoicelineitems] - 使用两个外键以多对多样式将发票与产品连接起来。

    这就是大多数现成电子商务系统和小型企业会计系统的工作方式。

    如果您需要超级具体的跟踪,您当然可以变得更复杂,但您需要通过解释为什么单价模式不适用于您的用例来证明成本和复杂性是合理的。 (汽车经销商是一个示例,其中服务的跟踪方式与正常情况完全不同,服务/产品在单独的表中都与代表有关您的汽车的一个“问题”或“投诉”的行项目相关联。每个行项目都有一个产品组件和一个服务组件。)

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

    【讨论】:

      【解决方案2】:

      其实我会换一种方式:

      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
      

      关键是“可销售”抽象了服务和产品共有的东西。在您的情况下,这可能不是理想的解决方案,但它是其他人尚未提及的可行设计。

      附录:为确保记录准确,最受尊敬的销售/财务系统将为每个销售的每个订单项拍摄每个产品/服务记录的快照。因为我们应该无论如何为每次销售拍摄我们的产品记录快照,所以更简单、更直接的方法是让所有可销售商品共享一组核心字段。

      【讨论】:

      • 谢谢@svidgen。我实际上只是考虑了抽象,而不是实际含义。
      • 我喜欢你的方法,但我会将 saleable_id、units 和 total 从 sale 移到 sale_datails。此外,我将在 sales_detail 上复制价格,每个人都这样做,因为价格可以改变。
      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        我已经不止一次这样做了:

        餐桌产品: - product_id (PK) - 描述 - product_type_id (FK)

        表格发票:

        • invoice_id
        • client_id

        表 invoice_line: - invoice_id - product_id - product_type_id - 价格

        表产品类型 - product_type_id - 描述

        所以,在你的最后一张桌子上,设置两个项目: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 多人在做这样的事情,直到今天,没有任何缺陷。

        希望对你有帮助。

        【讨论】:

          【解决方案5】:

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

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

          希望对你有帮助。

          【讨论】:

            【解决方案6】:

            在撰写本文时,我相信答案忽略了一件事:

            当某物的价格发生变化时会发生什么?

            我提出这个是因为你特别提到了报告。

            现在所有以前的销售都显示新价格吗?所有服务是否以相同的费率计费(或者某些客户是否获得折扣?)

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

            这可能无关紧要 - 但你必须决定这样的事情。这就是为什么领域模型会受到很多人的欢迎。

            所以我建议选项 1,但考虑到产品/服务销售表应该引用已售产品和已售服务,而不是“原产地”产品/服务。

            【讨论】:

              猜你喜欢
              • 2018-09-03
              • 2013-10-27
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-09-03
              • 2014-07-29
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多