如何将单个记录与一个或多个PK相关联

时间:2015-04-30 20:57:08

标签: database tsql

如果我有一个单独的记录代表一个可销售的项目:

ItemID | Name
-------------
101    | Chips
102    | Candy bar
103    | Beer

我需要在这些项目与一种或多种不同类型的PK之间建立关系。例如,一家公司可能有一个包含芯片的库存;一家商店可能有一个包含薯条和糖果的库存,夜班可能带有薯条,糖果棒和啤酒。我们有不同类型的ID:CompanyID,StoreID,ShiftID。

我的第一个虽然是“哦,只需创建链接表,将公司链接到库存项目,存储到库存项目,然后转移到库存项目”,这样,如果我需要查找任何这些实体的库存集合,我可以明确地查询它们。但是,UI显示我应该可以任意编译列表(例如,显示公司a的所有库存项目,所有西谷商店和位于东谷商店的Team BrewHa)然后按其各自的实体显示它们:

Company A
---------
- Chips

West Valley 1
-------------
- Chips
- Candy Bar

West Valley 2
-------------
- Chips

BrewHa (East Valley 6)
--------------------
- Chips
- Candy Bar
- Beer

所以,我的第一个问题是将查询基于所提供的信息(他们给我的ID类型),然后将它们与一些额外的信息组合在一起(如IDType + ID等候选键),以便结果看起来像这样:

IDType | ID | InventoryItemID
------------------------------
1      |100 | 1
2      |200 | 1
2      |200 | 2
2      |201 | 1
3      |300 | 1
3      |300 | 2
3      |300 | 3

我想这会起作用,但对我来说似乎非常低效和做作;我甚至不确定那个sproc的参数是如何工作的......所以我对每个人的问题是:这是否是正确的方法?任何人都可以解释替代或更好的方法来解决创建和管理这些关系的问题吗?

3 个答案:

答案 0 :(得分:1)

由于我不知道此数据的用途/用途,因此很难确定您想要的内容。我不熟悉规范化,但也许明星模式可能适合你。请记住,我正在使用我最好的猜测术语。我的想法看起来像这样:

tbl_Current_Inventory (事实表)记录当前库存

InventoryID  INT NOT NULL FOREIGN KEY REFERENCES tbl_Inventory(ID),
CompanyID    INT     NULL FOREIGN KEY REFERENCES tbl_Company(ID),
StoreID      INT     NULL FOREIGN KEY REFERENCES tbl_Store(ID),
ShiftID      INT     NULL FOREIGN KEY REFERENCES tbl_Shift(ID),
Shipped_Date DATE --not really sure, just an example,
CONSTRAINT clustered_unique CLUSTERED(InventoryID,CompanyID,StoreID,ShiftID)

tbl_Inventory (事实表2)

ID NOT NULL INT,
ProductID INT NOT NULL FOREIGN KEY REFERENCES tbl_Product(ID),
PRIMARY KEY(ID,ProductID)

tbl_Store (事实表3)

ID INT PRIMARY KEY,
CompanyID INT FOREIGN KEY REFERENCES tbl_Company(ID),
RegionID INT FOREIGN KEY REFERENCES tbl_Region(ID)

tbl_Product (维度表)

ID INT PRIMARY KEY,
Product_Name VARCHAR(25)

tbl_Company (维度表)

ID INT PRIMARY KEY,
Company_Name VARCHAR(25)

tbl_Region (维度表)

ID PRIMARY KEY,
Region_Name VARCHAR(25)

tbl_Shift (维度表)

ID INT PRIMARY KEY,
Shift_Name VARCHAR(25)
Start_Time TIME,
End_Time TIME

所以有点解释。每个维度表仅包含不同的值,例如 tbl_Region 。列出每个地区的名称一次和ID。

现在对于 tbl_Current_Inventory ,它将包含所有列。我有他们的公司ID和StoreID是有原因的。因为此表可以保存公司库存信息(NULL StoreID和NULL shiftID)并且它可以保存商店库存信息。

然后至于查询这个,我会创建一个连接每个表的视图,然后简单地查询视图。然后当然有索引,但我认为你没有要求。另请注意,每个维度表只有一列。我的猜测是你可能会有更多的列,然后只是名称的东西。

总的来说,这有助于消除大量重复数据。并且在性能方面取得了良好的平衡,而不是过于复杂的数据结构。实际上,如果你对它进行一个视图,并查询视图,它应该表现得相当好,特别是如果你添加一些好的索引。

这可能不是一个完美的解决方案,甚至不是你需要的解决方案,但希望它至少能给你一些想法或一些方向。

如果您需要更多解释或其他任何内容,请告诉我。

答案 1 :(得分:0)

在规范化数据库中,您可以通过创建一个表来实现多对多关系,该表定义实体之间的关系,就像您最初想象的那样。它可能看起来很人为,但它为您提供了所需的功能。在你的情况下,我会创建一个关系表,称为“Carries”,主键为(ProductId,StoreId,ShiftId)。有时你可以打破规范化的规则,但它带有副作用。

我建议你选择一本关于设计关系数据库的好书。以下是几个主题的首发:

http://en.wikipedia.org/wiki/Entity%E2%80%93relationship_model http://en.wikipedia.org/wiki/Database_normalization

答案 2 :(得分:-1)

您需要将其分解为属于商店和班次的库存 库存确实不属于公司 - 商店属于公司
如果公司直接持有库存,那么我会创建一个商店名称仓库
商店属于区域
不要为UI设计 - 将数据放入3NF

表格:

Company   ID, name    
Store     ID, name 
Region    ID, name   
Product   ID, name   
Shift     ID, name 

CompanyToStore  CompanyID, StoreID          (composite PK)

RegionToStore   RegionID, StoreID           (composite PK)

Inventory       StoreID, ShiftID, ProductID (composite PK) 

复合PK不仅有效,而且可以防止重复 连接表应具有自己的ID作为PK
让他们管理的关系是PK

如果您希望公司在所有班次中进行报告,您可能会有这样的查询

select distinct store.Name, Product.Name 
  from Inventory 
  join Store 
    on Inventory.StoreID = Store.ID 
  join CompanyToStore 
    on Store.ID = CompanyToStore.StoreID 
   and CompanyToStore.CompanyID = X

在区域内存储计数

select RegionName, count(*) 
  from RegionToStore 
  join Region 
    on Region.ID = RegionToStore.RegionID 
 group by RegionName