设计问题

Dat*_*bie 6 database-design

我有一份“供应商”和“商店”清单。每个供应商都向商店出售“物品”,但根据地理位置或供应商与商店之间的特殊协议而有特殊定价。这在概念上表示为“价格组”。

因此,例如,item 1可能$10适用于与供应商的“白金”价格组相关联的商店。同一商品可能$12适用于与该供应商的“黄金”价格组相关联的商店。

我将上述概念建模如下:

在此处输入图片说明

问题:

  1. 设计是否标准化?我特别关心supplier_price_groupsstore_price_groups
  2. 我是否会在可扩展性方面遇到这种设计的问题,尤其是在尝试查询特定商店所有商品的价格时?

Tom*_*att 3

分阶段构建您的数据库。到目前为止,您拥有三个主要实体:商店、供应商、商品。供应商和物料之间的关系看起来很简单。一个供应商可以提供许多物品,并且一个物品可以通过许多供应商获得。这意味着供应商和项目之间有一个交集/联结表。作为这种关系的一部分,可以包括默认价格,即在没有其他安排生效的情况下有效的价格。

create tabel SupplierItem(
    SupplierID   int not null,
    ItemID       int not null,
    DefaultPrice currency not null,
    constraint   PK_SupplierItem primary key( SupplierID, ItemID ),
    constraint   FK_SupplierItem_Supplier foreign key( SupplierID )
        references Suppliers( ID ),
    constraint   FK_SupplierItem_Item foreign key( ItemID )
        references Items( ID )
);
Run Code Online (Sandbox Code Playgroud)

现在您有两种调整价格的方法。但我们要介绍第三种折扣,因为它很常见——基于数量的折扣。这可以看作是供应商和项目之间关系的一个属性。

create table VolumeDiscount(
    SupplierID   int not null,
    ItemID       int not null,
    MinVol       int not null,
    Discount     tinyint not null check( Discount between 0 and 99 ),
    constraint   PK_VolumeDiscount primary key( SupplierID, ItemID, MinVol )
);
Run Code Online (Sandbox Code Playgroud)

我省略了与已定义相同的 FK 定义。折扣是基于交易量 >= MinVol 且 < 下一个最高 MinVol 列表的价格折扣百分比。折扣最好定义为浮点值——但这毕竟只是为了说明。

现在我们来看看可选的基于地理位置的折扣。这表明还有另一个交集表。它还假设有一个地理位置表。

create table GeoDiscount(
    SupplierID   int not null,
    GeoID        int not null,
  -- ItemID       int not null,
    Discount     tinyint not null check( Discount between 0 and 99 ),
    constraint   PK_GeoDiscount primary key( SupplierID, GeoID[, ItemID] ),
    constraint   FK_GeoDiscount_Geo foreign key( GeoID )
        references GeoLocations( ID )
);
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,如果每件商品有不同的折扣,这很容易扩展,尽管我不认为经常需要这样做。

最后,一些供应商和一些商店之间有折扣协议。这可能会变得棘手,因为供应商可以向商店提供所有商品的全面折扣和/或某些商品的单独折扣。

create table StoreDiscounts(
    StoreID     int not null,
    SupplierID  int not null,
    ItemID      int,
    Discount    tinyint not null check( Discount between 0 and 99 ),
    constraint  FK_StoreDiscounts_Store foreign key( StoreID )
        references Stores( ID ),
    constraint  UQ_StoreDiscounts unique( StoreID, SupplierID, ItemID )
);
Run Code Online (Sandbox Code Playgroud)

请注意,自然键(StoreID、SupplierID、ItemID)是使用唯一约束而不是主键约束定义的。这是因为 ItemID 可为空。如果 ItemID 为 NULL,则折扣适用于商店从供应商处购买的所有商品。相反或此外,供应商可以针对每个商品提供折扣。或者对所有商品提供一般折扣(ItemID 为 NULL),但对选定的商品子集提供不同折扣。在后一种情况下,每件商品的折扣可以添加到一般折扣中,或者可以取代一般折扣。设计本身并不需要或强调其中之一。使用哪种方案必须记录在案。这些折扣是否替换或添加到标准批量折扣将是在此模式设计之外确定的另一个业务规则。

当然,这是一个未经测试的设计,最后一个表可能可以改进。但就数据完整性而言,设计相当“严格”,并且简单地标准化为 BCNF。显然,用于此设计的查询将相当复杂,但这始终是这种所需灵活性的成本。您的工作是让用户的工作变得更轻松,而不是您自己的工作。