7

我们有一个如下图所示的购物车,该设置运行良好,除了一个致命缺陷。如果您下订单,则订单与产品相关联,因此如果我在您购买产品后更新产品,我无法向您展示您想要产品在您购买时的样子(包括价格)。这意味着我们需要版本控制。

当前架构

我目前的计划是,当创建新产品或变体或编辑现有产品时,在数据库中创建产品或变体的副本。购买时,将订单链接到版本,而不是产品。

这看起来相当简单,除了我可以看到我们唯一不需要版本化的是类别(因为没有人关心它属于什么类别。)。所以我们需要版本:

  • 产品
  • 变体
  • 每个版本的键 -> 值对属性
  • 图片

我目前的想法是,

注意: 当创建产品时,也会创建默认变体,这不能被删除。

  • 创建产品时
    • 将产品插入产品表中。
    • 创建默认变体
    • 将产品复制到 products_versions 表中
      • 用 product_id 列替换当前 id 列
      • 添加标识列
    • 将变体复制到 variables_versions 表中
      • 用 variant_id 列替换当前 id 列
      • 添加标识列
      • 将 product_id 列替换为 product_version_id 列

  • 编辑产品时
    • 将产品更新到产品表中。
    • 将产品复制到 products_versions 表中
      • 用 product_id 列替换当前 id 列
      • 添加标识列
    • 将所有产品变体复制到 variables_versions 表中
      • 用 variant_id 列替换当前 id 列
      • 添加标识列
      • 将 product_id 列替换为 product_version_id 列
    • 将所有 variant_image_links 复制到 variant_Image_link_version 表中
      • 将当前的 variant_id 列替换为 variant_version_id 列

  • 添加变体时
    • 将变体添加到变体表中。
    • 将产品复制到 products_versions 表中
      • 用 product_id 列替换当前 id 列
      • 添加标识列
    • 将所有产品变体复制到 variables_versions 表中
      • 用 variant_id 列替换当前 id 列
      • 添加标识列
      • 将 product_id 列替换为 product_version_id 列

  • 编辑变体时
    • 更新变体表中的变体。
    • 将产品复制到 products_versions 表中
      • 用 product_id 列替换当前 id 列
      • 添加标识列
    • 将所有产品变体复制到 variables_versions 表中
      • 用 variant_id 列替换当前 id 列
      • 添加标识列
      • 将 product_id 列替换为 product_version_id 列
    • 将所有 variant_image_links 复制到 variant_Image_link_version 表中
      • 将当前的 variant_id 列替换为 variant_version_id 列

所以最终的结构看起来像Full Size

现在这一切看起来都很棒,除了看起来有很多重复的数据,例如,如果我们更新产品,我们会复制变体,即使它们在插入后不会更新。此外,这似乎需要做很多工作。

有没有更好的方法来做到这一点?

4

2 回答 2

5

您可以执行 ERP(也可能是工资单)系统执行的操作:添加开始和结束日期/时间。所以...

  • 根据共同日期,变体和价格与其产品相匹配。
  • 所有查询默认在当前日期运行,并且每个表之间的连接还需要考虑重叠/相交的日期范围。parent_start_date <= child_start_date AND parent_end_date >= child_end_date
  • 对于每个价格变化或变体,您最终会得到重复的行,但是当产品价格变化时,您不需要保持更新尽可能多的记录(如变体 ID)。
  • 需要确保使用有效日期。PS:使用系统的最大日期作为最新/最近记录的结束日期时间。

顺便说一句,一些相关的问题:

于 2012-11-14T18:48:36.677 回答
0

另一种方法是永远不要编辑或删除您的数据,只创建新数据。在 SQL 术语中,您曾经对表运行的唯一操作是 INSERT 和 SELECT。

要完成您想要的,每个表都需要以下列:

  • version_id - 这将是您的主键
  • id - 这将是保存对象版本的东西(例如,查找产品的所有版本,SELECT * FROM products WHERE id = ?)
  • 创立日期
  • is_active - 你没有删除任何东西,所以你需要标记以(逻辑上)删除数据

有了这个,您的产品表将如下所示:

CREATE TABLE products (
  version_id CHAR(8) NOT NULL PRIMARY KEY,
  id INTEGER NOT NULL,
  creation_date TIMESTAMP NOT NULL DEFAULT NOW(),
  is_active BOOLEAN DEFAULT true,
  name VARCHAR(1024) NOT NULL,
  price INTEGER NOT NULL
);

CREATE TABLE variants (
  version_id CHAR(8) NOT NULL PRIMARY KEY,
  id INTEGER NOT NULL,
  creation_date TIMESTAMP NOT NULL DEFAULT NOW(),
  is_active BOOLEAN DEFAULT true,
  product_version_id CHAR(8) NOT NULL,
  price INTEGER NOT NULL,
  override_price INTEGER NOT NULL,
  FOREIGN KEY (product_version_id) REFERENCES products(version_id)
);

现在,插入任一表

  1. 生成唯一的version_id(有几种策略,一种是使用数据库序列,或者对于MySQL使用ant AUTO_INCREMENT)。
  2. 生成一个标识。此 id 对于产品的所有版本都是一致的。

要更新表中的一行,必须插入整个图表,例如,要更新产品,必须插入新产品和新变体。(这里有很大的优化空间,但最容易从未优化的解决方案开始。)

例如,更新产品

  1. 生成唯一的 version_id
  2. 使用相同的 id
  3. 插入新产品变体。变体将与链接到您正在“更新”的产品的先前版本的变体相同,除了 product_version_id 不同。

该主体可以扩展到您的所有表。

要查找产品的最新版本,您需要使用 creation_date 列来获取最近创建的产品。

这个模型将使用更多空间,但我认为这可能是一个公平的权衡,因为它很简单:只有 INSERT 和 SELECT,并且数据永远不会发生变异。

于 2012-11-16T04:38:07.627 回答