I am fairly new with database design so thank you for all input for helping me with a little problem I have designing the structure of a database. Basically I want to set up a many-to-many-to-many relationship between 3 main tables and a forth that is linked to the third. I'll try to explain it using an example.
Suppose I have tables created to show the relationship between SCENE, ACTOR, and ACTION. SCENE can have more than one ACTOR, and each ACTOR can have more than one ACTION. This is what I have worked out so far:
Have an intermediate ScenesActors table that just lists the SceneID and ActorID (along with its own ID field [SceneActorID] as primary key).
You then have the ScenesActorsActions table which has the SceneActorID and ActionID (along with its own ID field [SceneActorActionID] as PK).
The ScenesActors table lists each actors are in which scenes.
The ScenesActorsActions table lists what they do.
Scenes --< ScenesActors >-- Actors
Actions --< ScenesActorsActions
However, in the design of my database, say Actions already has a one-to-many relationship with another table titled ActionPossibilities in which every row was a possible action that could take place (essentially making the possible actions that could occur dynamic). How then would you effectively create the relationship described above? The problem i am running into is that the primary key for the Actions table is used as a foreign key in the ActionPossibilities table. Is something like this possible under the current design?
Just have four tables: Scene, Actor, Action and ActionPossibilities. Scene and Actor should be simple: SceneID, SceneDescription, etc. Same for Actor. Action is your main table. It should have a FKs to SceneID, ActorID, and ActionPossibilitiesID (not the other way around). From there, you can query Action to get whatever combination of actors/scenes/actions you need.
Related
Title is the question. When should a relationship in an ER diagram be given its own table in a RDBMS? For instance, one mail courier(with attributes eid and surname) can deliver a number of packages but a package(attributes,pid, sent_By, going_to) can only have one mail courier. Would it make sense to make a table for the relationship called delivers(with an attribute of the time that the package was delivered)? or should the eid of the mail_courier and time_delivered from the deliver relationship be added to the package entity? Also, what would be an example when you would not want to add the attributes to the package entity?
I think what you are trying is to create a one-to-many relationship between two entities. And for that, there is no need to create a separate table; as you mentioned in your question, just add those two attributes to the package table.
Where you would need to create a separate table is when you want to achieve many-to-many relationship between two entities. For example, take twitter's followers. One user can have many followers and a follower can follow many users. You can't do that the relational way without creating a new table with just those two columns.
I have a design problem with regards to Entity Framework model relationship
I have this model in the edmx
Business Rule:
A Participant can have multiple Roles so I create a relationship table ParticipantRoles that has 1-to-Many relationship on the Participant and the Role table
The Problem:
In order to get the Participant's Role value, I have to drill down through Participant->ParticipantRole->Role (see JSON output below)
The Question:
In EF, how to design the table relationship to bypass the ParticipantsRole table. I want to access the Role in something like this Particant.Role and not Participant.ParticipantsRole.Role
You say A Participant can have multiple Roles. And of course, a Role can have multiple Participants. So basically this is a many-to-many association.
Entity Framework will only map pure many-to-many associations (without connecting class) when the junction table only has two foreign keys. In your case, if the table ParticipantsRole only would have had a primary key consisting of ParticipantId and RoleId at the time of generating the model the class ParticipantsRole would not have been created. You would have had Participant.Roles and Role.Participants as navigation properties.
However, the model has been generated with ParticipantsRole and you want to get rid of it. (Or not, I'll get back to that).
This is what you can do:
Remove ParticipantRoles from the class diagram.
Modify the database table ParticipantRoles so it only has the two FK columns, that both form the primary key.
Update the model from the database and select ParticipantsRole in the Add tab.
This should give you a model with a pure many-to-many association.
However, think twice before you do this. M2m associations have a way of evolving into 1-m-1association (as you've got now). The reason is that sooner or later the need is felt to record data about the association, so the junction table must have more fields and stops being a pure junction table. In your case I can imagine that one day participant's roles must have a fixed order, or one marked as default. It can be a major overhaul to change a m2m association into 1-m-1 in a production environment. - Something to consider...
I'm trying to design a database structure using best practice but I can't get my head around something which I'm sure is fundamental. The DB is for the users(100+) to subscribe to which magazines(100+) they read.
I have a table for the usernames, user info and magazine titles, but I'm unsure where to list the magazines that each user follows. Do I add a column in the user table and link it to the magazine table or would each user be setup with their own "follow" table that lists the magazine there? I'm getting myself confused I think so any help would be great.
Regards
Ryan
What you're struggling with is called a many-to-many relationship.
To solve this problem, you need a third table--perhaps called user_magazines. This third table should two key fields, one from the user table and the other from the magazine table. For example, user_id column and a magazine_id column. This is called a compound key. With both of these columns, you are now able to discern which books have been read by a whichever user.
This is best understood visually:
In the picture above you can see that the third table (the middle table, stock_category) enables us to know what stock item belongs to which categories.
First of all, you must understand a many-to-many relationship, like take your example of users and magazines. First understand the scenario : A single user can follow many magazines, and a single magazine can be followed by many users, so there exists a many-to-many relationship between users and magazines.
Whenever there exists many-to-many relationship between two entities, we have to introduce a third entity between them which is called an associative entity!
so you have to introduce a third entity named as per your choice and it will be containing information about which user is following which magazine
you can go to http://sqlrelationship.com/many-to-many-relationship/ for better understanding using diagrams
You should have a users table, with an auto-incrementing primary key, username, and anything else you want to store about that user.
Next, a magazines table which contains another auto-incrementing primary key, the name of the mag and anything else you need to store about that magazine.
Finally, a subscriptions table. this should have an auto-incrementing primary key (actually that's not really necessary on this table but personally I would add it), a user_ID column and a magazine_ID column.
To add a subscription, just add a new record to the subscription table containing the ID of the user and the ID of the relevant magazine. This allows for users to subscribe to multiple magazines.
If you want to get fancy you can add referential integrity constraints to the subscriptions table - this tells the database management system that a particular column is a reference to another table, and can specify what to do upon modifying it (for example you could have the DBMS automatically delete subscriptions owned by a particular user if that user is deleted)
You definitely do NOT want to add a column to the user table and have it refer to the magazine table. Users would only be able to follow or subscribe to one magazine which doesn't reflect the real world.
You'll want to have a join table that has a userId and a magazineId. For each magazine that a user subscribes to there will be one entry in the join table.
I'm inferring a little bit about your table structure but if you had:
User (id, login)
Magazine (id, name)
User_Magazine (userId, magazineId)
Perhaps this last table should be called subscription because there may be other information like the subscription end date which you'd want to track and that is really what it is representing in the real world.
You'd be able to put an entry into the User_Magazine table for every subscription.
And if you wanted to see all the magazines a user with the login jdoe had you'd do:
SELECT name
FROM User, Magazine, User_Magazine
WHERE login = 'jdoe'
AND User.id = User_Magazine.userId
AND Magazine.id = User_Magazine.magazineId
You should create a separate table called UserMagazineSubs. Make the UserID + MagazineTile ID as a composite key.
This table will capture all User and Magazine relationship details.
A User_To_Magazine table, that has two columns - UserId and MagazineId, and the key is composite containing both columns
I am starting a new Project for a website based on "Talents" - for example:
Models
Actors
Singers
Dancers
Musicians
The way I propose to do this is that each of these talents will have its own table and include a user_id field to map the record to a specific user.
Any user who signs up on the website can create a profile for one or more of these talents. A talent can have sub-talents, for example an actor can be a tv actor or a theatre actor or a voiceover actor.
So for example I have User A - he is a Model (Catwalk Model) and an Actor (TV actor, Theatre actor, Voiceover actor).
My questions are:
Do I need to create separate tables to store sub-talents of this user?
How should I perform the lookups of the top-level talents for this user? I.e. in the user table should there be fields for the ID of each talent? Or should I perform a lookup in each top-level talent table to see if that user_id exists in there?
Anything else I should be aware of?
before answering your questions... i think that user_id should not be in the Talents table... the main idea here is that "for 1 talent you have many users, and for one user you have multiple talent".. so the relation should be NxN, you'll need an intermediary table
see: many to many
now
Do I need to create seperate tables to store sub-talents of this
user?
if you want to do something dynamic (add or remove subtalents) you can use a recursive relationship. That is a table that is related to itself
TABLE TALENT
-------------
id PK
label
parent_id PK FK (a foreign key to table Talent)
see : recursive associations
How should I perform the lookups of the top-level talents for this
user? I.e. in the user table should
there be fields for the ID of each
talent? Or should I perform a lookup
in each top-level talent table to see
if that user_id exists in there?
if you're using the model before, it could be a nightmare to make queries, because your table Talents is now a TREE that can contain multiple levels.. you might want to restrict yourself to a certain number of levels that you want in your Talent's table i guess two is enough.. that way your queries will be easier
Anything else I should be aware of?
when using recursive relations... the foreign key should alow nulls because the top levels talents wont have a parent_id...
Good luck! :)
EDIT: ok.. i've created the model.. to explain it better
Edit Second model (in the shape of a Christmas tree =D ) Note that the relation between Model & Talent and Actor & Talent is a 1x1 relation, there are different ways to do that (the same link on the comments)
to find if user has talents.. join the three tables on the query =)
hope this helps
You should have one table that has everything about the user (name, dob, any other information about the user). You should have one table that has everything about talents (id, talentName, TopLevelTalentID (to store the "sub" talents put a reference to the "Parent" talent)). You should have a third table for the many to many relationship between users and talents: UserTalents which stores the UserID and the TalentID.
Here's an article that explains how to get to 3rd NF:
http://www.deeptraining.com/litwin/dbdesign/FundamentalsOfRelationalDatabaseDesign.aspx
This is a good question to show some of the differences and similarities between object oriented thinking and relational modelling.
First of all there are no strict rules regarding creating the tables, it depends on the problem space you are trying to model (however, having a field for each of the tables is not necessary at all and constitutes a design fault - mainly because it is inflexible and hard to query).
For example perfectly acceptable design in this case is to have tables
Names (Name, Email, Bio)
Talents (TalentType references TalentTypes, Email references Names)
TalentTypes (TalentType, Description, Parent references TalentTypes)
The above design would allow you to have hierarchical TalentTypes and also to keep track which names have which talents, you would have a single table from which you could get all names (to avoid registering duplicates), you have a single table from which you could get a list of talents and you can add new talent types and/or subtypes easily.
If you really need to store some special fileds on each of the talent types you can still add these as tables that reference general talents table.
As an illustration
Models (Email references Talents, ModelingSalary) -- with a check constraint that talents contain a record with modelling talent type
Do notice that this is only an illustration, it might be sensible to have Salary in the Talents table and not to have tables for specific talents.
If you do end up with tables for specific talents in a sense you can look at Talents table as sort of a class from which a particular talent or sub-talent inherits properties.
ok sorry for the incorrect answer.. this is a different approach.
The way i see it, a user can have multiple occupations (Actor, Model, Musician, etc.) Usually what i do is think in objects first then translate it into tables. In P.O.O. you'd have a class User and subclasses Actor, Model, etc. each one of them could also have subclasses like TvActor, VoiceOverActor... in a DB you'd have a table for each talent and subtalent, all of them share the same primary key (the id of the user) so if the user 4 is and Actor and a Model, you would have one registry on the Actor's Table and another on the Model Table, both with id=4
As you can see, storing is easy.. the complicated part is to retrieve the info. That's because databases dont have the notion of inheritance (i think mysql has but i haven't tried it).. so if you want to now the subclases of the user 4, i see three options:
multiple SELECTs for each talent and subtalent table that you have, asking if their id is 4.
SELECT * FROM Actor WHERE id=4;SELECT * FROM TvActor WHERE id=4;
Make a big query joining all talent and subtalent table on a left join
SELECT * from User LEFT JOIN Actor ON User.id=Actor.id LEFT JOIN TvActor ON User.id=TvActor.id LEFT JOIN... WHERE User.id=4;
create a Talents table in a NxN relation with User to store a reference of each talent and subtalents that the User has, so you wont have to ask all of the tables. You'd have to make a query on the Talents table to find out what tables you'll need to ask on a second query.
Each one of these three options have their pros and cons.. maybe there's another one =)
Good Luck
PS: ahh i found another option here or maybe it's just the second option improved
So I know the convention for naming M-M relationship tables in SQL is to have something like so:
For tables User and Data the relationship table would be called
UserData
User_Data
or something similar (from here)
What happens then if you need to have multiple relationships between User and Data, representing each in its own table? I have a site I'm working on where I have two primary items and multiple independent M-M relationships between them. I know I could just use a single relationship table and have a field which determines the relationship type, but I'm not sure whether this is a good solution. Assuming I don't go that route, what naming convention should I follow to work around my original problem?
To make it more clear, say my site is an auction site (it isn't but the principle is similar). I have registered users and I have items, a user does not have to be registered to post an item but they do need to be to do anything else. I have table User which has info on registered users and Items which has info on posted items. Now a user can bid on an item, but they can also report a item (spam, etc.), both of these are M-M relationships. All that happens when either event occurs is that an email is generated, in my scenario I have no reason to keep track of the actual "report" or "bid" other than to know who bid/reported on what.
I think you should name tables after their function. Lets say we have Cars and People tables. Car has owners and car has assigned drivers. Driver can have more than one car. One of the tables you could call CarsDrivers, second CarsOwners.
EDIT
In your situation I think you should have two tables: AuctionsBids and AuctionsReports. I believe that report requires additional dictinary (spam, illegal item,...) and bid requires other parameters like price, bid date. So having two tables is justified. You will propably be more often accessing bids than reports. Sending email will be slightly more complicated then when this data is stored in one table, but it is not really a big problem.
I don't really see this as a true M-M mapping table. Those usually are JUST a mapping. From your example most of these will have additional information as well. For example, a table of bids, which would have a User and an Item, will probably have info on what the bid was, when it was placed, etc. I would call this table... wait for it... Bids.
For reporting items you might want what was offensive about it, when it was placed, etc. Call this table OffenseReports or something.
You can name tables whatever you want. I would just name them something that makes sense. I think the convention of naming them Table1Table2 is just because sometimes the relationships don't make alot of sense to an outside observer.
There's no official or unofficial convention on relations or tables names. You can name them as you want, the way you like.
If you have multiple user_data relationships with the same keys that makes absolutely no sense. If you have different keys, name the relation in a descriptive way like: stores_products_manufacturers or stores_products_paymentMethods
I think you're only confused because the join tables are currently simple. Once you add more information, I think it will be obvious that you should append a functional suffix. For example:
Table User
UserID
EmailAddress
Table Item
ItemID
ItemDescription
Table UserItem_SpamReport
UserID
ItemID
ReportDate
Table UserItem_Post
UserID -- can be (NULL, -1, '', ...)
ItemID
PostDate
Table UserItem_Bid
UserId
ItemId
BidDate
BidAmount
Then the relation will have a Role. For instance a stock has 2 companies associated: an issuer and a buyer. The relationship is defined by the role the parent and child play to each other.
You could either put each role in a separate table that you name with the role (IE Stock_Issuer, Stock_Buyer etc, both have a relationship one - many to company - stock)
The stock example is pretty fixed, so two tables would be fine. When there are multiple types of relations possible and you can't foresee them now, normalizing it into a relationtype column would seem the better option.
This also depends on the quality of the developers having to work with your model. The column approach is a bit more abstract... but if they don't get it maybe they'd better stay away from databases altogether..
Both will work fine I guess.
Good luck, GJ
GJ