为多对多关系(产品的变体)的组合设计SQL模式

Zak*_*ziz 19 sql schema database-administration e-commerce database-schema

我希望这个标题有点帮助.我正在使用MySQL作为我的数据库

我正在建立一个产品数据库,我不知道如何处理产品变化的存储价格/ SKU.产品可能有无限的变化,每个变化组合都有自己的价格/ SKU /等.

这就是我现在设置我的产品/变体表的方法:

PRODUCTS
+--------------------------+
| id | name | description  |
+----+------+--------------+
| 1  | rug  | a cool rug   |
| 2  | cup  | a coffee cup |
+----+------+--------------+

PRODUCT_VARIANTS
+----+------------+----------+-----------+
| id | product_id | variant  | value     |
+----+------------+----------+-----------+
| 1  | 1          | color    | red       |
| 2  | 1          | color    | blue      |
| 3  | 1          | color    | green     |
| 4  | 1          | material | wool      |
| 5  | 1          | material | polyester |
| 6  | 2          | size     | small     |
| 7  | 2          | size     | medium    |
| 8  | 2          | size     | large     |
+----+------------+----------+-----------+

(`products.id` is a foreign key of `product_variants.product_id`)
Run Code Online (Sandbox Code Playgroud)

我用这个示例数据创建了一个SQLFiddle:http://sqlfiddle.com/#!2/2264d/1

允许用户输入任何变体名称(product_variants.variant)并可以为其分配任何值(product_variants.value).用户可以输入的变化/值的数量不应该有限制.

这就是我出现问题的地方:每次有人添加一个以前不存在的变体的产品时,每次变化都要存储价格/ SKU而不添加新的表/列.

每个变体可能具有相同的价格,但SKU对于每个产品是唯一的.例如,产品1有6种不同的组合(3种颜色*2种材料),而产品2只有3种不同的组合(3种尺寸*1).

我曾考虑将组合存储为文本,即:

+------------+-----------------+-------+------+
| product_id | combination     | price | SKU  |
+------------+-----------------+-------+------+
| 1          | red-wool        | 50.00 | A121 |
| 1          | red-polyester   | 50.00 | A122 |
| 1          | blue-wool       | 50.00 | A123 |
| 1          | blue-polyester  | 50.00 | A124 |
| 1          | green-wool      | 50.00 | A125 |
| 1          | green-polyester | 50.00 | A125 |
| 2          | small           | 4.00  | CD12 |
| 2          | medium          | 4.00  | CD13 |
| 2          | large           | 3.50  | CD14 |
+------------+-----------------+-------+------+
Run Code Online (Sandbox Code Playgroud)

但必须有更好的,标准化的方式来表示这些数据.假设情况:我希望能够搜索低于10美元的蓝色产品.使用上面的数据库结构,如果不解析文本就不可能做到这一点,这是我想要避免的.

任何帮助/建议表示赞赏=)

sah*_*idu 34

对您的问题应用规范化解决方案是给定的.在Fiddle上运行并查看它

小提琴

CREATE TABLE products 
    (
     product_id int auto_increment primary key, 
     name varchar(20), 
     description varchar(30)

    );

INSERT INTO products
(name, description)
VALUES
('Rug', 'A cool rug'  ),
('Cup', 'A coffee cup');

create table variants (variant_id int auto_increment primary key,
                       variant varchar(50)
                       );
insert into variants (variant)
values ('color'),('material'),('size') ;   
create table variant_value(value_id int auto_increment primary key, 
                           variant_id int ,
                           value varchar(50)
                           );

insert into variant_value (variant_id,value)
values (1 ,'red'),(1 ,'blue'),(1 ,'green'),
        (2 ,'wool'),(2 ,'polyester'),
        (3 ,'small'),(3 ,'medium'),(3 ,'large');



create table product_Variants( product_Variants_id int  auto_increment primary key,
                            product_id int,
                            productVariantName varchar(50),
                            sku varchar(50),
                            price float
                            );




create table product_details(product_detail_id int auto_increment primary key,
                             product_Variants_id int,

                             value_id int
                             );

insert into product_Variants(product_id,productVariantName,sku,price)
values (1,'red-wool' ,'a121',50);

insert into product_details(product_Variants_id , value_id)
values( 1,1),(1,4);

insert into product_Variants(product_id,productVariantName,sku,price)
values (1,'red-polyester' ,'a122',50);

insert into product_details(product_Variants_id , value_id)
values( 2,1),(2,5);
Run Code Online (Sandbox Code Playgroud)

  • 你能解释一下product_details表的用法吗? (5认同)
  • 你能解释一下product_details表的用法吗? (4认同)

Den*_*rdy 17

您的部分问题源于产品与SKU之间的混淆.

当您销售"XYZ套衫,尺寸M,蓝色模型"时,后者对应于SKU.它作为XYZ套衫(产品)销售,它具有一组属性(大小和颜色),每个属性都有自己的一组潜在值.并非后者的所有可能组合都可能产生有效的可交付成果:你不会找到荒谬的薄和长牛仔裤.SKU,产品,属性,属性值.

当用户想要10美元的蓝色套衫时,他实际上是在产品类别中寻找SKU.

我希望上述内容可以解决您的困惑以及您的问题和问题源于何处.

在架构方面,你想要这样的东西:


制品

  • #product_id
  • 名称
  • 描述

或者,还添加:

  • 价钱
  • 有现货

这是营销相关表.没有其他的.如果营销之外的任何事情在您的应用程序中使用了产品,那么您将最终陷入痛苦的世界.

价格(如果存在)是用于在SKU中为空时填充字段的主要价格.这使得价格输入更加用户友好.

in_stock是一个有希望的自我解释的旗帜,理想情况下由触发器维持.如果与该产品相关的任何 SKU有库存,则应该是真的.


产品属性

  • PRODUCT_ID
  • #attribute_id
  • 名称

product_attribute_values

  • attribute_id
  • #value_id

这只包含颜色,大小等等,以及它们的值,如蓝色,红色,S,M,L.

请注意product_id字段:为每个产品创建一组新的属性和值.尺寸根据产品而变化.有时它是S,M,L等; 其他时候,它将是38,40,42,什么不是.有时候,尺寸就足够了; 其他时候,你需要宽度和长度.蓝色可能是该产品的有效颜色; 另一个可能会提供海军,皇家蓝,蓝绿色等等.不要认为某个产品的属性与另一个产品的属性之间存在任何关系; 它们存在时的相似之处完全是装饰性的和巧合的.


单品

  • PRODUCT_ID
  • #sku_id
  • 价钱

(可选)添加:

  • 名称
  • 条码
  • 股票

这相当于发货的可交付成果.

它实际上是下面最重要的表格.这个而不是product_id几乎肯定是应该在客户订单中引用的内容.它也应该被引用到库存等等.(我见过后两点的唯一例外是当你卖出一些非常通用的东西.但即便如此,根据我的经验来处理这个问题的更好方法是在可互换的SKU之间投入一个nm关系.)

如果添加名称字段,则主要是为了方便起见.如果保留为null,则使用应用程序端代码使其与通用产品的名称相对应,必要时使用相关的属性名称和值进行扩展.填充它允许用更自然的东西("Levis'501,32x32,深蓝色")重新描述后者的通用名称("Levis'501,W:32,L:32,颜色:深蓝色").

如果重要的话,从长远来看,使用触发器可以更好地维护库存,并在后台使用复式簿记架构.这样就可以区分现有的库存和今天可用的货物(这是您实际需要的数字)与库存但已售出的数量,这些都是您将遇到的大量现实场景.哦,而且......如果您需要出售以千克或升为单位的任何东西,它偶尔会是一个数字而不是整数.如果是这样,请务必添加额外的is_int标志,以避免客户向您发送.1笔记本电脑的订单.


product_variants

  • PRODUCT_ID
  • #sku_id
  • #attribute_id
  • value_id

为了生成默认名称,这会将交付项的id与相应的属性和值链接起来.

主键打开(sku_id,attribute_id).

您可能会发现product_id字段存在异常.它是,除非你添加外键引用:

  • SKU(product_id,sku_id)
  • product_attributes(product_id,attribute_id)
  • product_attribute_values(attribute_id,value_id)

(如果您决定添加这些外键,请不要忘记相应元组上的额外唯一索引.)


最后还有三个评论.

首先,我想再次强调,就流量而言,并非所有属性和值的组合都能产生有效的可交付成果.宽度可能是28-42,长度可能是28-42,但你可能不会看到一个严重的28x42紧身牛仔裤.最好不要默认自动填充每个产品的每个可能的变体:添加UI以根据需要启用/禁用它们,默认选中它,以及名称,条形码和价格字段.(名称和价格通常会留空;但有一天,您只需要在蓝色套头衫上进行销售,理由是颜色已经停止,而您继续销售其他选项.)

其次,请记住,如果您需要额外管理产品选项,那么许多实际上是伪装的产品属性,而那些不产生新SKU的产品属性在库存时也必须考虑到.例如,用于笔记本电脑的更大HD选项实际上是由于(非常有效的)UI考虑而伪装成选项的相同产品(正常与大HD尺寸)的变体.相比之下,将笔记本电脑作为圣诞礼物包装是一个真正的选择,它在记账条款中引用了完全独立的SKU(例如.8m的礼品包装) - 并且,如果您需要提出平均边际成本,则需要一小部分工作人员的时间.

最后,您需要为您的属性,它们的值以及后续变体提供一种排序方法.为此,最简单的方法是在属性和值表中添加一个额外的位置字段.


xwo*_*ker 5

我会用4个表:

generic_product: product_id, name, description 
Run Code Online (Sandbox Code Playgroud)

例如1,'地毯','咖啡地毯'/ 2,'马克杯','咖啡杯'

generic_product_property: product_id, property_id, property_name 
Run Code Online (Sandbox Code Playgroud)

例如1,10,'颜色'/ 1,11''材料'

sellable_product: sku, product_id, price 
Run Code Online (Sandbox Code Playgroud)

例如'A121',1,50.00 /'A122',1,45.00

sellable_product_property: sku, property_id, property_value 
Run Code Online (Sandbox Code Playgroud)

例如'A121',10,'red'/'A121',11,'wool'/'A122',10,'green'/'A122',11,'wool'

这将允许您的用户为您想要的可销售产品定义任何属性.

您的应用程序必须确保其业务逻辑完全描述sellable_products(检查每个适用的通用产品属性是否定义了可售产品属性).