【问题标题】:Database Design: product and product combo数据库设计:产品和产品组合
【发布时间】:2011-11-04 13:01:04
【问题描述】:

假设我正在销售一些product。有时,product 实际上是其他product 的组合。例如,假设我正在销售:

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

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

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

建议?

注意:我想知道是否可以使用父子关系将产品和产品组合放在一个表中。有了一张桌子,记录销售额就不难了。我只需要实施一个业务规则,即在已经针对该组合记录销售时编辑产品组合,该组合实际上会产生一个新条目。不过,可能会变得混乱。

【问题讨论】:

    标签: mysql database-design


    【解决方案1】:

    这取决于您实际需要对系统执行的操作。需要跟踪库存的系统需要了解“组合餐”需要从库存中扣除一个热狗和 32 盎司苏打水(或其他)。然而,一个只记录订单和金额的系统并不真正关心“进入”套餐的内容——只关心你卖了一份并得到了报酬。

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

    您可以有一些菜单项,巧合的是,它们与库存项具有相同的名称,但是对于这些菜单项对待它们的方式与您使用组合项的方式相同,并将单个记录粘贴到链接表:

     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
    

    仅仅构建这个例子,事实证明即使是卑微的热狗也有两个组成部分(你必须数一下面包),而不仅仅是一个。为了提出最简单的情况(具有单个组件的菜单项),我将 Soda 添加到菜单中。但是,请考虑,如果您要盘点非食品(杯子),那么即使是简单的苏打水也将包含两个组件(如果您要盘点吸管,则三个组件)。

    请注意,这种设计不会有用于处理组合项和非组合项的特殊代码路径。所有与菜单相关的功能将仅使用menu_items 表,所有与库存和食品准备相关的功能将JOIN menu_itemsrecipes 和(如果需要其他字段)到inventory_items

    您需要对可选成分(酸菜、调味品、辣椒等)和可从不同库存项目中选择的成分(在此模型中表示为 *soda)进行特殊处理,但这应该可以帮助您入门。

    【讨论】:

    • 嗨拉里,我还在考虑你的解决方案。我试图解决的问题实际上不仅仅是关于食物。也可以是其他物品。我正在尝试分析您的解决方案,看看它是否足以满足我的需要。
    • 我做销售时要记录什么?我是否存储了对menu_items PK 的引用?如果是这样,这意味着一旦销售了该特定项目,我将需要保留该记录以用于历史目的。这样我就知道menu_item的“Hot Dog”的销售实际上是指销售时的热狗和热狗面包。如果该 menu_item 稍后被编辑(例如,表示热狗、热狗面包、芥末),那么该编辑实际上应该导致在 menu_item 的表中创建一个新条目。
    • 另外,我可以通过复制recipes 中的关联记录,在销售记录中存储menu_item 的热狗的含义。如果 Hot Dog 的含义稍后发生变化,那也没关系。这意味着什么已经存储在销售记录中。我想我不应该允许在销售该项目后硬删除 menu_item(再次保留历史数据);我只想为它设置一个标志。想法?
    【解决方案2】:

    你的方法都可以。但至少还有另一种解决问题的方法,即对产品组合应用折扣(这意味着您也可以有选择地分配折扣),例如

    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=?
    

    【讨论】:

      【解决方案3】:

      我建议你从“订单”和“项目”的角度来考虑。一个订单由许多项目组成。项目可以是不同的“产品”。因此,订单的示例可以是:

      1) 热狗

      2) 苏打水

      3) 热狗 + 苏打水

      项目的示例可以是:

      A) 热狗

      B) 苏打水

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

      【讨论】:

      • 组合价格通常低于单个产品的总和。
      • 是的 - 在代码中定义组合列表,如果订单包含组合列表,则在该项目上应用定义的折扣。这个逻辑没有放在数据库中!想象一下今天你给了 5% 的折扣,明天你想把它改成 3%……或者你想添加/删除“组合”……
      猜你喜欢
      • 2011-11-27
      • 1970-01-01
      • 2011-07-30
      • 1970-01-01
      • 2013-01-09
      • 2014-02-12
      • 2017-06-01
      • 2018-08-27
      • 2020-04-29
      相关资源
      最近更新 更多