2011-11-04 90 views
4

说我卖出product。有时,product实际上是其他product的组合。例如,说我卖一个:数据库设计:产品和产品组合

  • 热狗
  • 苏打
  • 热狗+苏打组合

我应该如何模拟这样的事情?我是否应该有一个product表来列出各个产品,然后是描述组合的product_combo表,以及与productproduct_combo相关联的另一个表以列出组合中的产品?这对我来说似乎很简单。

但是,如果我想将所有销售记录在一张表中,该怎么办?意思是,我不想要product_sales表和product_combo_sales表。我希望所有的销售都在一张桌子上。我有点不确定如何以这种方式对产品和产品组合进行建模,之后我可以将所有销售记录在一张表中。

对此提出建议?

注:我想知道是否可以将产品和产品组合放在一张使用父 - 子关系的表中。用一张桌子,然后录制销售将不会很难。我只需要实现一个业务规则,即在已经针对该组合编辑了一个产品组合时,编辑实际上会导致一个新条目。虽然可能会变得混乱。

回答

4

这取决于您实际需要如何处理您的系统。需要跟踪库存的系统需要了解,“组合餐”需要通过一个热狗和32盎司苏打(或其他)来清点库存。然而,一个只追踪订单和美元的系统并不真正在意组合餐会有什么“进入” - 只有你卖掉了一个并获得了报酬。

也就是说,假设您需要库存系统。您可以通过稍微改变您的定义来降低复杂性。考虑(1)库存物品和(2)菜单项。您的inventory_items表格包含您购买并追踪为库存的物品(热狗,苏打水等)。您的menu_items表格包含您销售的物品(Big Dog Combo Meal,热狗(仅限三明治)等)。

你可以有,巧合的是,具有相同的名称作为库存项目,但对于对待他们,你做一个组合项目以同样的方式,坚持一个记录插入链接表这些菜单项的一些菜单项:

inventory_items   menu_items  recipes (menu_item, inventory, qty) 
---------------   ------------  ---------- 
hot dog     Hot Dog   Hot Dog, hot dog, 1 
hot dog bun    Hamburger  Hot Dog, hot dog bun, 1 
hamburger patty (4oz)  Big Dog Combo Hamburger, hamburger patty (4oz), 1 
hamburger bun    Soda (32oz)  Hamburger, hamburger bun, 1 
cola          Big Dog Combo, hot dog, 1 
ginger ale         Big Dog Combo, hot dog bun, 1 
              Big Dog Combo, *soda, 32 
              Soda (32oz), *soda, 32 

只是构建这个例子,事实证明,即使是低热狗也有两个组件(你必须计算发髻),而不仅仅是一个。为了提出最简单的情况(一个单一组件的菜单项),我在菜单中添加了苏打水。但是,考虑一下,如果你打算清点非食品物品(杯子),那么即使是一个简单的苏打水也会有两个组件(三个如果你正在清理吸管)。

请注意,使用此设计,将不会有处理组合项目和非组合项目的特殊代码路径。所有与菜单相关的功能将只使用menu_items表格,所有库存和食物准备相关功能将JOINmenu_itemsrecipes和(如果需要额外的字段)到inventory_items

您需要对可选组件(酸菜,津津有味,辣椒等)以及可以从不同库存项目中选择的组件(在此模型中表示为苏打)进行特殊处理,但这会让您开始。

+0

嗨拉里,我还在想你的解决方案。我试图解决的问题实际上并不仅仅是食物。它也可能是其他项目。我试图分析你的解决方案,看它是否足够满足我需要的。 – StackOverflowNewbie

+0

我在做销售时记录什么?我是否存储对'menu_items'的PK的引用?如果是这样,那意味着一旦出售该特定物品,我就需要保留该记录以用于历史目的。这样我就知道出售menu_item的“热狗”实际上意味着热狗和热狗包子。如果该menu_item稍后被编辑(例如,意味着热狗,热狗包,芥末),那么该编辑应该实际上导致在menu_item的表中创建新的条目。 – StackOverflowNewbie

+0

或者,我可以在销售记录中存储menu_item的热狗通过复制'recipes'中的相关记录来表示的意思。如果热狗的意思后来改变,那很好。这意味着什么已经存储在销售记录中。我想我不应该允许一个menu_item的硬销售一旦出售(再次保存历史数据);我只是为它设置一个标志。思考? – StackOverflowNewbie

0

我建议你根据“订单”和“项目”来思考。一个订单由许多项目组成。项目可以是不同的“产品”。因此,对于订单实例可以是:

1)热狗

2)苏打

3)热狗+苏打为物品

例子可以是:

A)热狗

B)苏打水

也可以通过这种方式在销售订单表中保留销售。 我不认为你需要在数据库中拥有“组合”的价值。 这是应该在代码中应用的业务逻辑,而不是在数据库中应用。 您可以稍后在代码中应用所有折扣。

+0

组合的价格通常比单个产品的总和低。 – StackOverflowNewbie

+1

是的 - 在代码中定义组合列表,并且如果某个订单包含组合列表,则对该项目应用定义的折扣。这个逻辑不被放置在数据库中!想象一下,今天你给5%的折扣,明天你想改变它为3%...或者你想添加/删除“组合”... – hovanessyan

0

你们的方法都行。但至少有一种方法可以解决将产品折扣应用于产品组合的问题(这意味着您也可以选择性地分摊折扣),例如

CREATE TABLE products 
(
    id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, 
    name VARCHAR(128), 
    description TEXT, 
    price INT 
); 
CREATE TABLE combo_discounts 
(
    id NOT NULL PRIMARY KEY AUTO_INCREMENT, 
    name VARCHAR(128), 
    description TEXT 
); 
CREATE TABLE cd_products 
(
    cd_id INT /* REFERENCES combo_discounts.id */, 
    p_id INT /* REFERENCES product.id */ 
    price_reduction INT 
); 
CREATE TABLE sales 
(
    id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, 
    location ...whatever... 
); 
CREATE TABLE sales_items 
(
    sale_id INT /* REFERENCES sales.id */ 
    p_id INT /* REFERENCES product.id */ 
    cd_discount INT /* REFERENCES cd_products.cd_id */ 
); 

但是记住,你需要使用程序代码分配折扣销售(和标志,当您去各卖出项),以解决有人买2个热狗和一个问题苏打(因此只获得一次折扣)。

...,因此总价格销售是

SELECT SUM(p.price)-SUM(cd.price_reduction) 
FROM sales s INNER JOIN sales_items si ON (si.sale_id=s.id) 
    LEFT JOIN cd_products cdp ON (si.cd_discount = cdp.cd_id 
     AND si.p_id=cdp.p_id) 
AND s.id=?