Should I create a reference field or a third content type to represent a many-to-many relationship in Drupal 8? - database

I have a student table and a course table that have a many-to-many relationship (a student can take many courses, and a course can be taken by many students).
If I am implementing the above data model as a database, I would create a third table to represent the many-to-many relationship.
But I want to implement the above data model in Drupal 8. I think that in Drupal 8 there are two ways to implement the above data model:
I can create a reference field in one of the two content types
(student or course) that points to the other content type.
I can create a third content type that have two reference fields
that points to the student and course content types.
Am I correct that these two ways are valid? and if I am correct, which one should I choose?

I think you're right, I would have suggested both ways.
As long as their connection doesn't have any additional parameters (e.g. date of subscription etc.), I would choose the entity reference within the students' content type.

Both of these are valid, and there's an additional option of having a corresponding reference field on each of your content types.
The best option comes down to maintain ability for your editors.
As per #c1u31355, if there is additional "connection" metadata, then a third content type is the way to go (or maybe a paragraph).
If it's a straight connection A <> B, and you only want the reference in one place, then ask yourself where is most convenient to add that data? Is it easier to create a course and then link to 30 students, or are you wanting to add courses to students as you create them? Quicker at creation, but harder to maintain.
Either way, using IEF as I suggested in one of your other questions will help.
As a final thought, having a 3rd content type could cause all sorts of issues unless you control the fields well, something like limiting it to only having one student with a bunch of courses, or vise versa, and in that case maintenance will be easier by just putting a reference field on the content type where you have restricted the field to one value.

Related

the correct structure relation between student vs teacher comparing to user table

What is the correct database structure design for user table if I have instructor vs student?
Is it correct to create each one in separate table and the id is the user table
Like this?:
Or creating new flag field (1 or 2) to define the students from the instructors like this?:
I know both will work, but I'm asking to get the most professional answer for this problem.
For me i'm working on Laravel and creating a relations there is very easy.
The first option - separate tables for each subtype of user - is recommended when you have subtype-specific attributes, relationships or constraints; and a known fixed set of subtypes.
The second option - a type indicator column - is recommended when you don't have any subtype-specific attributes, relationships or constraints; and works better for user-managed subtypes.
It doesn't matter whether you have overlapping or disjoint subtypes. Either can be recorded in separate tables; or overlapping subtypes can be indicated via multiple boolean fields and disjoint via a single field.

Is it a good idea to create a db with a generic table entity that can be decorated with a role and metadatas?

I've been thinking about creating a database that, instead of having a table per object I want to represent, would have a series of generic tables that would allow me to represent anything I want and even modifying (that's actually my main interest) the data associated with any kind of object I represent.
As an example, let's say I'm creating a web application that would let people make appointments with hairdressers. What I would usually do is having the following tables in my database :
clients
hairdressers: FK: id of the company the hairdresser works for
companies
appointments: FK: id of the client and the hairdresser for that appointment
But what happens if we deal with scientific hairdressers that want to associate more data to an appointment (e.g. quantity of shampoo used, grams of hair cut, number of scissor's strokes,...) ?
I was thinking instead of that, I could use the following tables:
entity: represents anything I want. PK(entity_id)
group: is an entity (when I create a group, I first create an entity which
id is then referred to by the FK of the group). PK(group_id), FK(entity_id)
entity_group: each group can contain multiple entity (thus also other groups): PK(entity_id, group_id).
role: e.g. Administrator, Client, HairDresser, Company. PK(role_id)
entity_role: each entity can have multiple roles: PK(entity_id, role_id)
metadata: contains the name and type of the metadata aswell as the associated role and a flag that describes if its mandatory or not. PK(metadata_id), FK(metadata_type_id, role_id)
metadata_type: contains information about available metadata types. PK(metadata_type_id)
metadata_value: PK(metadata_value_id), FK(metadata_id)
metadata_: different tables for the different types e.g. char, text, integer, double, datetime, date. PK(metadata__id), FK(metadata_value_id) which contain the actual value of a metadata associated with an entity.
entity_metadata: contains data associated with an entity e.g. name of a client, address of a company,... PK(entity_id, metadata_value_id). Using the type of the metadata, its possible to select the actual value of a metadata for this entity in the corresponding table.
This would allow me to have a completely flexible data structure but has a few drawbacks:
Selecting the metadatas associated with an entity returns multiple rows that I have to process in my code to create the representation of the entity in my code.
Selecting metadatas of multiple entities requires to loop over the same process as above.
Selecting metadatas will also require me to do a select for each one of the metadata_* table that I have.
On the other hand, it has some advantages. For example, instead of having a client table with a lot of fields that will almost never be filled, I just use the exact number of rows that I need.
Is this a good idea at all?
I hope that I've expressed clearly what I'm trying to achieve. I guess that I'm not the first one who wonders how to achieve that but I was not able to find the right keywords to find an answer to that question :/
Thanks!

Database Design for Facebook "likes"

New to database design and I was wondering how to efficiently design something like Facebook likes with future scalability in mind.
Let's say you have 3 tables: users, photos and albums.
Let's say a user can like either a photo or an album.
Should I use 1 table for both types of likes?
This would probably mean it would have an user_id, like_type(0-photo, 1-album etc), like_value(the id value of whatever content it is, whether it is photo_id or album_id)?
or have 2 different tables for each likes (ex. photos_likes and albums_likes)?
which would only contain user_id and photo/album_id
I want to make sure that the database design is clean and semi-scaleproof whether we add many more objects in the future(videos, comments, notes, etc) or have a ton of likes.
Thanks!
You could try a inherited table approach see implementing table inheritence for more indepth detail.
But essentially it works just like inheritence in code, you have a base table 'Like' and then tables which 'inherit' from it 'CommentLike', 'PhotoLike' etc.
See attached diagram for a quick mockup.
Two different tables. This way if you ever have an object that you want to add likes to later you can just make a new table "object_likes" and store the likes there.
If you wanted to store them all in one table, you would need a type table, which would store all the types of objects, and in your like table you would have to reference the type_id. This would let you add types later.
To me the first method is much better.

Basic Database design. Use a another table or colum

I have a table that holds information about a particular Object, Say Item and has columns
ItemID, ItemName, price, ItemListingType.....LastOrderDate
One of the bits of information, ItemListingType could be one of 10 different types
such as:
private, gov, non-gov, business... etc (strings) and could be extended to more types in future.
Should I be using a column inside table ITEM or should I Use a separate table with two columns and put a foreign key in Item table to reference that (a one to many relationship)? Like:
ListingTypeID int
ListingTypeName varchar(MAX)
EDIT: how many values for a column, you will consider to use another table for that
2, 4 or what ?
Thanks
Use a separate table to store this kind of reference data. This is a tenet of normalization and will also enable easier caching because you are separating read-only and read-write data. my two cents...
Separate table.
What if you have a listing type not yet used?
Or delete the last item with type x?
Or need to change a value?
These are insert, update and delete anomalies, which is one reason for normalisation
I would definitely go for a "lookup" style column; that way you are not stumped when there future additions to the list of permissible listing types. You are also reducing redundancy and making it easier to change the designation of aparticular type of listing (if "gov" changes to "government agencies", then you only have to change it in one place).
You should do it with the second table that holds the ListingTypes and link to the id of that table from the one with the Objects...
Take a look at Relational Database and Relational model.
In situations like this I ask myself:
Can the Item have an undetermined number of Listing types? If yes, different table.
Do the specs say that there will never be more than 3 types? Depends. Sometimes I'll still go with a separate table, sometimes not. You get a feel for this after a while.
Will the Item ALWAYS have a single listing type? If yes, same table, single column.
Now to take matters one step further.
If an Item has zero or more listing types AND those listing types are actually shared (in other words two items could have the same listing type, then we have 3 tables: Items, ListingTypes, and a cross reference table to support a many to many relationship.
Clasically, you should use an extra table, because you won't have any duplication that way. It will also allow you to change the value for this listing in a single place. However, if you are very very sure that no types will be added, keep the column.

Table "Inheritance" in SQL Server

I am currently in the process of looking at a restructure our contact management database and I wanted to hear peoples opinions on solving the problem of a number of contact types having shared attributes.
Basically we have 6 contact types which include Person, Company and Position # Company.
In the current structure all of these have an address however in the address table you must store their type in order to join to the contact.
This consistent requirement to join on contact type gets frustrating after a while.
Today I stumbled across a post discussing "Table Inheritance" (http://www.sqlteam.com/article/implementing-table-inheritance-in-sql-server).
Basically you have a parent table and a number of sub tables (in this case each contact type). From there you enforce integrity so that a sub table must have a master equivalent where it's type is defined.
The way I see it, by this method I would no longer need to store the type in tables like address, as the id is unique across all types.
I just wanted to know if anybody had any feelings on this method, whether it is a good way to go, or perhaps alternatives?
I'm using SQL Server 05 & 08 should that make any difference.
Thanks
Ed
I designed a database just like the link you provided suggests. The case was to store the data for many different technical reports. The number of report types is undefined and will probably grow to about 40 different types.
I created one master report table, that has an autoincrement primary key. That table contains all common information like customer, testsite, equipmentid, date etc.
Then I have one table for each report type that contains the spesific information relating to that report type. That table have the same primary key as the master and references the master as well.
My idea for splitting this into different tables with a 1:1 relation (which normally would be a no-no) was to avoid getting one single table with a huge number of columns, that gets very difficult to maintain as your constantly adding columns.
My design with table inheritance gave me segmented data and expandability without beeing difficult to maintain. The only thing I had to do was to write special a special save method to handle writing to two tables automatically. So far I'm very happy with the design and haven't really found any drawbacks, except for a little more complicated save method.
Google on "gen-spec relational modeling". You'll find a lot of articles discussing exactly this pattern. Some of them focus on table design, while others focus on an object oriented approach.
Table inheritance pops up in a few of them.
I know this won't help much now, but initially it may have been better to have an Entity table rather than 6 different contact types. Then each Entity could have as many addresses as necessary and there would be no need for type in the join.
You'll still have the problem that if you want the sub-type fields and you have only the master contact, you'll have to know what table to go looking at - or else join to all of them. But otherwise this is a workable solution to a common problem.
Another possibility (fairly similar in structure, but different in how you think of it) is to simply put all your contacts into one table. Then for the more specific fields (birthday say for people and department for position#company) create separate tables that are associated with that contact.
Contact Table
--------------
Name
Phone Number
Address Table
-------------
Street / state, etc
ContactId
ContactBirthday Table
--------------
Birthday
ContactId
Departments Table
-----------------
Department
ContactId
It requires a different way of thinking of things though - instead of thinking of people vs. companies, you think of the various functional requirements for the task at hand - if you want to send out birthday cards, get all the contacts that have birthdays associated with them, etc..
I'm going to go out on a limb here and suggest you should rethink your normalization strategy (as you seem to be lucky enough to be able to rethink your schema quite fundamentally). If you typically store an address for each contact, then your contact table should have the address fields in it. Alternatively if the address is stored per company then the address should be stored in the company table and your contacts linked to that company.
If your contacts only have one address, or one (or even 3, just not 'many') instance of the other fields, think about rationalizing them into a single table. In my experience having a few null fields is a far better alternative than needing left joins to data you aren't sure exists.
Fortunately for anyone who vehemently disagrees with me you did ask for opinions! :) IMHO you should only normalize when you really need to. Where you are rethinking schemas, denormalization should be considered at every opportunity.
When you have a 7th type, you'll have to create another table.
I'm going to try this approach. Yes, you have to create new tables when you have a new type, but since this table will probably have different columns, you'll end up doing this anyway if you don't use this scheme.
If the tables that inherit the master don't differentiate much from one another, I'd recommend you try another approach.
May I suggest that we just add a Type table. Ie a person has an address, name etc then the student, teacher as each use case presents its self we have a PersonType table that has an entry from the person table to n types and the subsequent new tables teacher, alien, singer as the system eveolves...

Resources