电子商务的数据库设计问题

发布于 2024-12-13 04:38:49 字数 897 浏览 1 评论 0原文

假设我有 2 个“东西”可以出售:服务产品。每个都用一个表格来表示,该表格捕获了它们的独特属性(例如,服务可能有每小时费率,而产品可能有单价等)。

每次进行销售时,假设我需要捕获完全相同的销售数据,无论是否销售服务或产品。我该如何建模?

方法 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 会更好,因为我需要生成如下报告:给

  • 定时期的总销售额
  • 每个销售人员的总销售额
  • 等。

Say I have 2 "things" I can sell: service and product. Each is represented with a table that captures their unique attributes (e.g. service might have a per hour rate while product may have a per unit price, etc.).

Each time a sale is made, assume that I need to capture the exact same data about the sale regardless of whether the service or product is sold. How do I model this?

APPROACH 1:

  1. I create one table to hold the details of each sale
  2. I create two "mapping" tables to connect the product or service with the sale table

So, something like this:

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)

APPROACH 2:

Skip the mapping tables and just have separate tables to record sales for products and services.

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)

I feel approach 1 would be better since I would need to generate reports like:

  • Total sales for a given period
  • Total sales per sales person
  • etc.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

长亭外,古道边 2024-12-20 04:38:49

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

因此,这是我使用一个产品表对您的问题的正式回答:

  1. 构建 [产品] 表以包含 PricePerUnit 和 UnitOfMeasure
    (可以是小时,可以每个,可以,可以预订率
    标准服务)。这可以充分描述定价
    大多数小公司的产品/服务之间的模型差异。
  2. 现在在您的 [product_sale] 表中(又名“InvoiceLineItem”,在我的
    lingo),添加注释字段。在这个字段中你可以写
    有关所售产品/服务的详细信息。在服务的情况下,
    您可以输入一些注释供客户参考,例如
    “执行了X服务,调整了B小部件并完善了C调音
    因此,

在这个简单的示例中,您有三个表:

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

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

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

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

Your Approach 1 is more favorable than approach 2 for the reasons you listed. Being able to collect up data across all sales of any type and having multiple items in one sale. Approach 2 suggests that products and services are only ever sold 1 at a time and not bundled together. But I have to wonder why you want to separate the products and services in the first place? (This would be industry specific depending on your needs). Most ecommerce systems and small business accounting systems use a simpler model with one products table.

So here's my official answer to your question using one products table:

  1. Structure the [product] table to have PricePerUnit and UnitOfMeasure
    (could be hours, could be each, could be pairs, could be book rate
    for standard services). This can adequately describe the pricing
    model difference between products/services for most small companies.
  2. Now in your [product_sale] table (aka "InvoiceLineItem" in my
    lingo), add a notes field. In this field you could write
    detail regarding the product/service sold. In the case of a service,
    you might enter some notes for the customer to reference like
    "Performed X service, adjusted B widget and polished the C tuning
    knob".

So you have three tables in this simple example:

  • [products] - contains master data or your "catalog" of products and services including their pricing for some unit of measure.
  • [invoices] - contains your sale information or invoice header including date, transaction id, maybe sales person, etc.
  • [invoicelineitems] - connects invoices with products with two foreign keys in a many-to-many style.

This how most off-the-shelf ecommerce systems and small business accounting systems work.

You can definitely go more complex if you need super specific tracking, but you need to justify the costs and complexity by explaining why a price per unit schema won't work for your use case. (auto dealerships are an example where services are tracked totally differently than normal with services/products in separate tables both tied to line items which represent one "problem" or "complaint" about your car. Every line item has both a product component and a service component.)

UPDATE: It appears I wasn't clear enough in my original answer as @Doug pointed out. When you create an invoice for a sale, the current PricePerUnit is copied to the InvoiceLineItem record along with a QuantitySold field and any other data important to snapshot of the product master data in case you need to reverse the transaction. This ensures the invoice always maintains the same total, even if the products price changes in the future. It also allows you to reverse the invoice if a customer returns something and make sure the customer gets the same amount back as paid regardless of the current price.

横笛休吹塞上声 2024-12-20 04:38:49

实际上,我会采取不同的做法:

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

重点是“可销售”抽象了服务和产品的共同点。对于您的情况,这可能不是理想的解决方案,但它是其他人尚未提及的可行设计。

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

Actually, I'd do it differently:

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

The point being that "salable" abstracts things that are common to services and products. This may not be the ideal solution in your case, but it is a viable design that others haven't mentioned yet.

ADDENDUM: To ensure accurate records, most respected sales/financial systems will take a snapshot of each product/service record for each line item of each sale. Since we ought to be taking snapshots of our product records for every sale anyway, the easier and more straightforward approach is for all sellable goods to share a set of core fields.

飘然心甜 2024-12-20 04:38:49

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

Approach 1 is best suited for your purposes. And it is also better suited for middleware layer built on top of your database layer - you can easily put ORM solution over existing database structure modeled with first approach

大姐,你呐 2024-12-20 04:38:49

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

表产品:
- 产品 ID(主键)
- 描述
-product_type_id (FK)

表发票:

  • invoice_id
  • client_id

表invoice_line:
- 发票 ID
- 产品 ID
- 产品类型 ID
- 价格

表product_type
- 产品类型 ID
- 描述

因此,在最后一个表上,设置两个项目:1 - “产品”,2 - “服务”
产品将被创建为这样的“1”,“Banana”,“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 多人参与了类似的工作,直到今天,没有任何缺陷。

希望有帮助。

I've done it more than once this way:

table product:
- product_id (PK)
- description
- product_type_id (FK)

table invoice:

  • invoice_id
  • client_id

table invoice_line:
- invoice_id
- product_id
- product_type_id
- price

table product_type
- product_type_id
- description

So, on your last table, set two itens: 1 - "product", 2 - "service"
Products would be created like this "1", "Banana", "1" (it's a product);
Services would be created like this "2", "Oil change", "2" (it's a service);

Now, when creating you invoices, make sure you pass the product_type_id for the selected product into the invoice_line table. This will get you more performance while querying data like "SELECT * from invoce_line WHERE product_type_id = 2" - to get all the data of sell services. (1 for products).

So, you keep all your invoice data inside a unique table; you can get, for instance, all the client's services through a simple join query like (client_id would be 10):

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

This would do the trick for almost everything. I got 1000+ people working over something like this and, till today, no flaws.

Hope it helps.

提笔书几行 2024-12-20 04:38:49

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

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

希望有帮助。

The first approach is favorable if you are trying to normalize your db. In this case you can re-use sale entity's attributes with sale_id=xx for a different products. In the second you will need to duplicate a sale's attributes if your are selling more than one product/service per sale (sale transaction).

Quering by person/date range can be solve using index strategy/partitions. If you know that your data will grow fast... so it will be another question concerning DW project.

Hope it helps.

番薯 2024-12-20 04:38:49

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

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

我提出这个问题是因为您特别提到了报告。

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

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

这可能并不重要——但你必须做出这样的决定。这就是领域模型受到广泛欢迎的原因。

因此,我建议使用选项 1,但考虑到产品/服务销售表应引用 sell_product 和 sell_service,而不是“原始”产品/服务。

At the time of writing this, answers are, I believe, overlooking one thing:

What happens when the price of something changes?

I bring this up because you specifically mention reporting.

Do all previous sales now show the new price? Do all services bill at the same rate (or do some customers get a discount?)

I would argue that your domain concept of a "Sale" needs to contain "Sold Items" that are purely value objects.

It may not matter - but you have to decide things like that. That's why domain models get a lot of arm-waving.

So I'm suggesting option 1, but with consideration that the product/service sale table should refer to a sold_product and a sold_service rather than the 'origin' product/service.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文