Henrique Ramos
Henrique Ramos

Reputation: 85

Modelling many-to-many relation between more than two tables

I'm modelling a tier-list database using PostgreSQL. This is how it works:

Modeling details:

For modelling the relations between item-tier and item-tier_list, I thought about two scenarios:

  1. Creating a junction with a composite PFK key of item and tier_list with a nullable tier FK. The records with no tier value would be the unranked ones, while the ones with an assigned tier would be the ranked;
  2. Creating two M-N relations: one between item and tier, storing ranked items, and another between item and tier_list, storing unranked items.

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. Am I missing something?

First proposed solution model: enter image description here

Second proposed solution model: enter image description here

Upvotes: 1

Views: 201

Answers (1)

Luca Scarcia
Luca Scarcia

Reputation: 318

You can create a joint key using 3 different fields.

First of all, why using smallint and not 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).

Second, I strongly suggest to put ID_ before and not after the name of the filed used for lookup. 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.

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. Usign similar names can bring troubles in 2-3 years when you have to add things and you're not sure what's what. Better use distinctive names for the tables.

Tier (suggesting tblTiers or 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. Do you need to reuse the same ID for different tiers? If that ID has a meaning bring it out from the PK absolutely! PK must be simple counters, that will NEVER be changed. I saw people using the ID with a meaning for the end-user. 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.

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!

Now, the lookup table:

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).

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).

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. 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).

Upvotes: 1

Related Questions