简体   繁体   English

建模两个以上表之间的多对多关系

[英]Modelling many-to-many relation between more than two tables

I'm modelling a tier-list database using PostgreSQL.我正在使用 PostgreSQL 对层列表数据库进行建模。 This is how it works:这是它的工作原理:

  • A user can create a new Tier List;用户可以创建一个新的层列表;
  • A user can add as many tiers he wants to the list;用户可以在列表中添加任意多的层;
  • A user can add as many items as he can.用户可以添加尽可能多的项目。 Initially, the items are added to an "unranked" section (not assigned to any tier), then the user can rank them as he wants.最初,项目被添加到“未排名”部分(未分配到任何层),然后用户可以根据需要对它们进行排名。

Modeling details:建模细节:

  • A tier necessarily belongs to a tier_list;一个层必然属于一个tier_list;
  • An item can be in multiple tier_lists and in multiple tiers as well;一个项目可以在多个 tier_lists 中,也可以在多个层中;
  • An item added to a tier_list has not necessarily been added to one of the tiers.添加到 tier_list 的项目不一定已添加到其中一个层。

For modelling the relations between item - tier and item - tier_list , I thought about two scenarios:为了建模item - tieritem - tier_list之间的关系,我考虑了两个场景:

  1. Creating a junction with a composite PFK key of item and tier_list with a nullable tier FK.使用itemtier_list的复合 PFK 键和可为空的tier FK 创建联结。 The records with no tier value would be the unranked ones, while the ones with an assigned tier would be the ranked;没有tier值的记录将是未排名的记录,而具有指定tier的记录将是排名的;
  2. Creating two MN relations: one between item and tier , storing ranked items, and another between item and tier_list , storing unranked items.创建两个 MN 关系:一个在itemtier之间,存储排名的项目,另一个在itemtier_list之间,存储未排名的项目。

I feel like the first option would be easier to deal with when having to persist things like moving a product between tiers (or even unranking it), while the second looks more compliant to SQL standards.我觉得第一个选项在必须坚持诸如在层之间移动产品(甚至取消排名)之类的事情时更容易处理,而第二个看起来更符合 SQL 标准。 Am I missing something?我错过了什么吗?

First proposed solution model:首先提出的解决方案model: 在此处输入图像描述

Second proposed solution model:第二种建议的解决方案model: 在此处输入图像描述

You can create a joint key using 3 different fields.您可以使用 3 个不同的字段创建联合密钥。

First of all, why using smallint and not int?首先,为什么使用 smallint 而不是 int? Not fluent in Posgres, but it's usually better to have the biggest integer possible as primary key (things can grow faster than you expect).不流利使用 Posgres,但通常最好将最大的 integer 作为主键(事情的增长速度可能比您预期的要快)。

Second, I strongly suggest to put ID_ before and not after the name of the filed used for lookup.其次,我强烈建议将 ID_ 放在用于查找的文件名之前而不是之后。 It makes it easier to read.它使阅读更容易。

As how to build your tables:至于如何建立你的表:

Item物品

ID PK
Title
Descriptions

I see no problems here.我认为这里没有问题。 I'd just change the name in tblProducts, for easier reading.我只是更改 tblProducts 中的名称,以便于阅读。

Tier_List Tier_List

ID PK
Description

Works fine too.工作也很好。 Again I'll look for a better name.再次,我会寻找一个更好的名字。 I'd call this one tblTiers or tblLegues instead.我将其称为 tblTiers 或 tblLegues。 Usign similar names can bring troubles in 2-3 years when you have to add things and you're not sure what's what.当您必须添加东西并且不确定是什么时,使用相似的名称可能会在 2-3 年内带来麻烦。 Better use distinctive names for the tables.最好为表格使用独特的名称。

Tier (suggesting tblTiers or tblRankings)层级(建议 tblTiers 或 tblRankings)

ID PK
Tier_List_ID PK FK
Title
Description

Here I see a HUGE problem.在这里,我看到了一个巨大的问题。 For experience, I don't really understand why you create a combination key here with ID and Tier_List_ID.出于经验,我真的不明白你为什么在这里创建一个带有 ID 和 Tier_List_ID 的组合键。 Do you need to reuse the same ID for different tiers?您是否需要为不同的层重复使用相同的 ID? If that ID has a meaning bring it out from the PK absolutely, PK must be simple counters.如果那个ID有意义,绝对要从PK中带出来,PK一定是简单的反击。 that will NEVER be changed.那永远不会改变。 I saw people using the ID with a meaning for the end-user.我看到人们使用对最终用户有意义的 ID。 It was a total disaster, I can't even start describing the quantity of garbage data that that DB was containing, I suppose, because you were talking about ranking.这完全是一场灾难,我什至无法开始描述该数据库包含的垃圾数据的数量,我想,因为你在谈论排名。 that the ID there is a Rank, a level or something like that. ID有一个等级,一个级别或类似的东西。

The table should become该表应成为

ID PK uuid
Tier_List_ID FK 
Rank smallint
Title
Description

There's another reason why I had you do this: when you have a combined PK, certain DBRMs require you to use the same combined key in the lookup tables, and that can become messy fast!我让你这样做还有另一个原因:当你有一个组合的 PK 时,某些 DBRM 要求你在查找表中使用相同的组合键,这会很快变得混乱!

Now, the lookup table:现在,查找表:

tier_list_item (tblRankingLookup?) tier_list_item (tblRankingLookup?)

ID_Product FK PK
ID_Tier_List FK PK
ID_Tier FK PK

You don't need anything else to make it work smoothly, At least.至少,您不需要其他任何东西来使其顺利运行。 that's how I'd envision it, Instead I'd add an ID_User (because I'm not sure if all users can see all tiers and all rankings. or they can see only theirs).这就是我的设想,相反,我会添加一个 ID_User(因为我不确定是否所有用户都可以看到所有层级和所有排名。或者他们只能看到他们的)。

Addendum: if you need to have unique combinations of different elements, I'm pretty sure you can create a combined index and mark it as "unique" (don't remember the correct syntax, not sure it is the same in Postgres).附录:如果您需要不同元素的唯一组合,我很确定您可以创建一个组合索引并将其标记为“唯一”(不记得正确的语法,不确定它在 Postgres 中是否相同)。

In exmple, if you don't want the Tier table to have the rank repeated only once per tier_list_ID, you can create an index using tier_list_ID and Ranking and mark it unique.例如,如果您不希望 Tier 表在每个 tier_list_ID 中仅重复一次排名,则可以使用 tier_list_ID 和 Ranking 创建索引并将其标记为唯一。 This way a two tiers in the same tier_list will not have the same value for the field Rank (rank can still be null).这样,同一 tier_list 中的两个层将不会具有字段 Rank 的相同值(rank 仍然可以为空)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM