This is my users table.
User can either be a normal user or an author. There's really no difference aside from the fact that an author has published/posted a story.
There's also no difference to access/privilege levels as a normal user can access a story via profile and an author can access a story via profile and via dashboard. Dashboard is accessed from the user profile where it is listed in the published story as an action.(title - link to story profile, action1 dashboard - link to story dashboard, action2 delete)
So far so good.
The problem i encounter now is that, i have to add a review and notification system.
A user can review a story and an author. So long as a user has published at least 1 story he is considered an author.
A user receives notifications from bookmarked story updates(new chapter, any changes to the story(edit)).
If a user is an author, the user can receive notification if another user reviewed/rated his/her story and his/her profile.
I have encountered trying various ways to apply the above functions(i applied them successfully but the db designs are very bad - i also did not enforce any foreign key constraints on my database).
I am confused how to identify whether a review is for a story or an author.
If the review is for an author, how do i reference two foreign keys of user_id from the same table?(1 is the author, the other is the user who reviewed the author). -- writing to here, i think its inevitable i should separate the user table into two as normal and author. But the users table is still the same for an author and a normal user.
if the review is for a story, Do i add a story_id column to the review table and leave it null if the review is for an author and vice versa?
So i'll have author_id(fk) and story_id(fk) and one has to be null if the other has a value.(to distinguish if story or author review).
I also forgot to add, there's another table named user_profile that has a foreign key(user_id from user table).
Think of your tables in terms of real world things and the design will be most of the way there in my experience. You have users, which can access your website, so you'll need a Users table. You have authors, who can write content, so you'll need an Authors table. All of your authors are also users, so you'll want a relationship there. You DO NOT want to have your users spread across multiple tables when it comes to security (i.e., a distinct Authors and Users table that don't overlap). That would be a nightmare to maintain. A user writes something and now you suddenly need to move all of their data to the Authors table if you go that route.
Now, for your next issue, is a review of an author and a review of a book the same thing? No, they're two distinct things, so create two tables - one for each.
Users
-----
user_id
username
password
...
Authors
-------
user_id
...
AuthorReviews
-------------
user_id (FK to Users table for the user who made the review)
author_id (FK to Authors table for the author that the review is about)
rating
summary
date_added
BookReviews
-----------
user_id (FK to Users table for the user who made the review)
book_id (FK to a Books table)
rating
summary
date_added
For the AuthorReviews and BookReviews tables the primary key would simply be composite PKs on user_id/author_id and user_id/book_id assuming that a user can only review something once.
The user_id might be an autoincrementing ID or some other ID that you come up with, but the author_id would come from the Users table when the author row is created. It would be a PK in both tables. Note that this only works if authors MUST also be users. If you can have an author who is not a user then you'll need to adjust the model so that the author_id is also generated and then there is a linking table between Users and Authors to make the relationship there when it's needed.
At least this is where I would start with things.
BTW, you can easily have multiple foreign keys to the same table. Just give the columns different names in the child table, but they link back to the same column in the parent.
Related
I'm trying to figure out the best way to do this, I currently have 3 types of profiles, Artist, Business and Contractor, they have similar fields but specific fields for each one, and I want a Ratings table for all of them. Lets say:
CONTRACTOR Table
id
name
cpf
profile_pic
cover_pic
bio
profile_type_id
BUSINESS Table
id
name
cnpj(14)
address
profile_pic
cover_pic
bio
profile_type_id
ARTIST Table
id
name
profile_pic
cover_pic
bio
profile_type_id
*** Most of the fields are similar but I plan to add other specific fields for each table later...
and then I have a Ratings table as follows:
RATINGS Table
id
rating
comment
author_id
author_type_id
profile_id
profile_type_id
At first I thought of using profile_id and profile_type_id to refer to the profile that receives the rating, as using author_id and author_type_id (based on profile_type_id from other tables) to refer to the author, composite foreign keys, right? But Sequelize seems not to support it.
I also thought about having 3 tables for Ratings but this seems not to be an elegant solution (what if I need to create more profile types later?)
Then I thought about having additional info for profiles into other tables but not sure if this is a good solution too... any ideas?
I'm developing this project using Node JS, Express and Sequelize, javascript.
I'm about to design a db for a new project and I'm kinda stuck on some "concept" stuff.
My initial question is very similar to this one.
Relational table naming convention
That is:
"If I got a table "user" and then I got products that only the user
will have, should the table be named "user-product" or just "product"?
This is a one to many relationship."
In the above thread I found the answer by PerformanceDBA very useful and well written,
but I'm not sure about some points. Quoting part of the answer:
"It doesn't matter if user::product is 1::n. What matters is whether product is a separate entity and whether it is Independent, ie. it can exist on its own. Therefore product, not user_product. And if product exists only in the context of an user, ie. it is Dependent,
then user_product."
This is a very interesting point, but generates another question:
what exactly are the definitions of Independent and Dependent table?
Example 1, we have two tables:
The table User
Id
Username
FullName
The 1::n table Message, representing a collection of messages sent by the users
UserId (FK to User.Id)
Text
The Message table is dependent from the User table or not?
The question I'm asking to myself here, is: "Would the message entity exist without the user?" but I'm not sure about the answer, because it would be "the message would exist but would be anonymous." is this enough to make the Message table dependent from the User table (so i should name the table "UserMessage")?
Example 2, we have two tables:
The table User
Id
Username
FullName
The 1::1 table Profile, representing a user profile
UserId (FK to User.Id)
First Name
Last Name
Gender
Same question, is the table Profile dependent by the User table? I think it is, because a profile without a user would not really make sense.
I'm not sure though, so how can I decide safely if a table is dependent by another or not?
I think you may really have 3 entities to consider. User, product and user_product. Test relationships by describing them with a verb. The relationship between a user and a product is most likely a many-to-many (a user can order many products, and a product can be ordered by many users). This indicates that a composite table between them that takes the primary keys of both tables is needed (and maybe attributes only if they describe a fact about the user/product combination). user_product is what links a user with his products (and a product with who ordered it) and is thus dependent.
That said, in your examples the message and profile tables are dependent, since they cannot exist without a user (their primary key). Use user - user_message and user - user_profile.
Another example of an independent table would be a lookup table (code/description table).
To answer your last question, an entity is considered dependent if its primary key must exist in another entity before it can exist i.e you can't have a profile without a user so it is dependent.
I'm designing a web application for a school. So far, I'm stuck with the database which has these tables:
users
id
username
password
profile
user_id (FK)
name
last_name
sex
group_id (FK)
(other basic information)
... And other tables irrelevant now, like events, comitees, groups and so on.
So, the users table stores basic information about the login, and the profiles table stores all the personal data about the user.
Now, the *group_id* column in the profile table has a foreign key that references the ID column of the group in which the user is currently enrolled, in the groups table. A user can only be enrolled in one group at once, so there's no need for any additional tables.
The thing is that it doesn't make much sense to me declaring a relation like group HAS MANY profiles. Instead, the relation should be group HAS MANY users, but then, I would have to put a *group_id* column on the users table, which doesn't really fit in, since the users table only stores auth information.
On the other side, I would like to list all the users enrolled in a group using an ORM and getting the a users collection and not profiles. The way I see it, is that the users table is like the 'parent' and the profiles table extends the users table.
The same problem would occur when setting attendances for events. Should I reference the profile as a foreign key in the events_attendance table? Or should I reference the user ID?
Of course both solutions could be implemented and work, but which of them is the best choice?
I have dug a little and found that both solutions would comply with 3NF, so in theory, would be correct, but I'm having a hard time designing the right way my database.
This is a question of your own conventions. You need to decide what is the main entity, right after that you can easiy find a proper solution. Both ways are good, but if you think of User as of the main entity while Profile is a property then you should put GroupId into User, otherwise, if you mean User and Profile as a single entity, you can leave GroupId in Profile, and by this you're not saying group HAS MANY profiles but group HAS MANY users.
By setting a proper one-to-one relation (User-Profile) you can force your data integrity good enough.
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 have two tables, Users and People, both of which share a common attribute, email address, of which they should be allowed to have many email addresses.
I can see three options myself:
One link table with redundant columns:
Users [id,email_id] and People [id,email_id]
EmailAddress [id,user_id,person_id,email_id]
Emails [id,address,type]
Two link tables without redundancies:
Users [id,email_id] and People [id,email_id]
PersonEmail [id,person_id,email_id]
UserEmail [id,user_id,email_id]
Emails [id,address,type]
No link tables with redundant columns:
Users [id] and People [id]
Emails [id,address,type,user_id,person_id]
Does anyone have any idea what would be the best option, or if there is any other ways? Also, if anyone knows how to implement or feel it is better to have link tables without the generated id column please also specify.
Update: a User has many People, a person belongs to a User
First off, the relationship between user and e-mail is 1:N, not M:N, so in any case you don't need the "link" table EmailAddress.
You need to decide which of these possibilities is true for your application:
User is always person.
Person is always user.
There can be a person that is not user and there can be a user that is not person.
Option 1:
Assuming the option (1) is the correct one, the logical model should look like this:
The symbol between Person and User is "category", which at the level of the physical database can be implemented either:
as a "1 to 0 or 1" relationship between separate tables Person and User,
or a single table containing both person and user fields, where user fields are NULL for persons that are not also users.
If you have...
many user-specific fields,
there are user-specific foreign keys,
new kinds of persons could be added in the future
and you don't need to squeeze-out every last drop of performance,
...choose the implementation strategy with two tables.
If there are:
relatively few user-specific fields,
there are no user-specific relationships,
low "evolvability" is acceptable
and performance is of high importance,
...choose the implementation strategy with the single table.
Similar analysis can be done for each of the remaining possibilities...
Option 2:
Option 3:
If the two entities are conceptually related, then it might make sense to have one table. But if they are two different concepts, then in my experience it is best to have separate tables in order to avoid future confusion. And you're not going to take a big hit anywhere by doing so.
Isn't the User a Person (People)?
That would solve the redundant field issue right away.
----------
| Person |
----------
|
--------
| User |
--------
The User should have the single e-mail field, or mantain the relation with the e-mails table, since Person is an abstract concept not related to any application.
I would say start thinking about (re)modeling your schema, so you won't have problems like this.
Read the Multiple Table Inheritance in Rails guide, that should get you started.