Let`s say we have the table users. In this table users there are 2 types of users, admin and user. They are linked to an role table through a role_id column but this doesn't matters so much, we can ignore the role table.
An admin has like 5 additional columns for the details and the User has around 25 additional columns for the details.
One option will be to insert all the details columns in the users table, and make them NULL. When inserting a new admin, all the columns for user details will be NULL and when adding a new user all the columns for the admin details will be NULL.
The second option will be to create 2 more tables like users_details and admin_details there will be related to the user_id, and store all the details inside them. And in the users table i will keep only the login info.
Which one you think is the best and why ?
Related
I want to create a database which has a table named warehouse which contains the details of each product. I have another table named users. At present there are 2 users in the users table - ABC and DEF.
My main question is user ABC has it's own warehouse and so for user DEF. How can I use the warehouse table for 2 or more different users ?
One to one
If one user own only one warehouse then you should add user_id column in warehouse table. then reference the user_id from user table via foreign key.
One to many
if multiple user owns an warehouse then you should add warehouse column in user table. then reference the warehouse from warehouse table via foreign key.
Many to Many
if an user owns multiple warehouse and and warehouse has multiple owner then you should add a table like warehouse_users and add keep warehouse and user_id.
I am confusing about how to design table when have two table reference single column in another table.
For example, I have two type of user ( lets call them user1 and user2 ) because these two type user have multiple different information so I create two table for each of them, and each user have one account to login to system. So I create a table call account and let two table user1 and user2 reference to ID in table account. So when I have one account and I want to know which one this account belong to. It's quite inconvenient because I have to look for in two table.
Does it have solution for this problem ?
If you have an entity user, create just one table user for them.
A user is a user, no matter if he has some special role. There will be some common fields for all users, e.g. a name.
table user:
user id
user name
age
homepage
To have specific information for different types of users, you create specialisation table with information about these roles:
table role1:
user id
roleinfo1
roleinfo2
table role2:
user id
roleinfo3
roleinfo4
roleinfo5
This way, a user can have multiple roles at the same time, but you can of course limit them to just one.
If a user can only be one of those roles (that's called disjunct), you have the additional statndard way to add a column role to your user-table and put all the information side-by-side in the user table, leaving the ones that don't belong to the user-role null:
table user:
user id
user name
age
homepage
roletype
roleinfo1
roleinfo2
roleinfo3
roleinfo4
roleinfo5
Even if the user can belong to multiple classes and in case there is no overlap between the additional columns, you can of course use the last approach and add multiple flags (e.g. columns istype1 and istype2), though this is a non-standard-approach.
Update Just to clarify how you use the first solution: every user has an entry in table user, e.g. with user id = 1. This also makes sure that no user of roles user1 and user2 can have the same user id.
User id in the role tables is both primary key and a foreign key of the user table.
To make that user a user of role 1, you then add an entry to table role 1 with user id = 1. If he is (also) a user of role 2, you add an entry to table role2 with user id = 1.
You can join the tables to get the "whole" picture,
select * from user
left join role1 on user.`user id` = role1.`user id`
left join role2 on user.`user id` = role2.`user id`
This will, apart from the double id columns (that will basically can be treated as the marker istype1, istype2 in the comment to the seconds solution) and the missing role-column look exactly like the second method with just one table.
To check if user with user id = 1 is of role 1, you can check if role1.user id is null in this query, or check if user id = 1 is in table role1. To e.g. list all data for just role 1, you can use
select * from user join role1 on user.`user id` = role1.`user id`
(it uses a join instead of the left join, since and entry for role 1 has to exist).
In most cases you don't even need the specialized data, so you can just join your account-table with the user-table. In any case, you never have to worry about checking two tables (or even more, if you decide to add a 3rd kind of user).
Whats the point of the account table? If each user has one account, why don't you store the account columns in the User table.
Furthermore you can still make a parent user table for the columns they share and then make childtables for the specific users.
for example
Parent: User
Children: Employee/Customer
I have a web application which allows users to join multiple groups.
I have a 'users' table which stores details about the users (id, email, password, etc.) and a 'groups' table which stores details about the available groups (id, name, owner of group).
I have been researching the best way to store group memberships (i.e. which users are in which group, bearing in mind they can be members of multiple) - however I am still not sure what the most efficient solution would be.
Would you recommend I:-
Create a second table called 'group_memberships' and store the user's ID along with the corresponding group ID?
Store an array alongside the group particulars in the 'groups' table with the user IDs of its members?
Approach this task a different way?
The DBMS I am using is phpMyAdmin.
I would advise you to go with option 1; where you have a Mapping Table for linking Users & Groups.
The Users Table will have PK on User_ID.
The Groups table will have PK on Group_ID.
The Mapping table will have User_ID(FK) and Group_ID(FK).
Now you should have PK on these two columns together.
This will ensure you don't have duplicate entries.
What you're describing is called a many-to-many relationship in database terms. A user can belong to multiple groups, and groups have more than one user (or else they wouldn't be "groups"!).
Your first idea, the group_memberships table, is the accepted best way to model this relationship. Although you'll want to name it users_groups or something similar to reflect the fact it relates or associates those two tables. At its most basic, this association table needs three columns:
ID (primary key)
user_id (foreign key)
group_id (foreign key)
By JOINing to this table ON either user_id or group_id, you can find the related records from either side of the relationship. And you can do it right from a SQL query, without any additional code like you'd need if you stored an array.
I would definitely go with option 1 - creating the junction table 'group_memberships' - I have used this approach many times without problems. Don't forget to add an Index on the new table 'group_memberships' for columns: 'groupID' and 'userID'.
Option 2 is not scalable for a large amount of data, especially if groups have a lot of users.
UPDATE:
For info on Indexes, here is a good (and short) blog: https://blog.viaduct.io/mysql-indexes-primer/.
The first option is a right choice. Actually it is a materialized view for both user table and group table.
Just think materialized view as a extra table or a redundant data structure that denormalizes the user properties and group properties together for quick search.
Since if we do not have the view, when we query a group id to list all its users, we have to filter millions of users to check if he/she is in the certain group. It is a performance nightmare!
Mysql has tools to build this view very efficiently. You may build secondary index on this view columns for quick search, say, group id, group name, user id, user name or something else you hope to search with.
good luck :-)
I have a users database and a comments database on a website, and I want to give each user the ability to have a list of favorite comments, and I don't know exactly how to implement this.
Should I create a new table for each user containing the IDs of his/hers favorite comments or is there a better approach?
A common, normalized approach would be a many to many relationship.
The schema for such a table, at a minimum, would be:
user_id
comment_id
Where user_id and comment_id are foreign keys to the users and comments table, respectively.
I would use three tables :
The users table, containing every users, including their personal informations, etc ;
The comments table, containing every comments ;
The favorites table, containing the id of the row, the id of the user and the id of the comment.
I did not name each table well, you should think more about the tables' names (e.g: favorites is a bad name).
I had to implement the following into my database:
The activities that users engage in. Each activity can have a name with up to 80 characters, and only distinct activities should be stored. That is, if two different users like “Swimming”, then the activity “Swimming” should only be stored once as a string.
Which activities each individual user engages in. Note that a user can have more than one hobby!
So I have to implement tables for this purpose and I must also make any modifications to existing tables if and as required and implement any keys and foreign key relationships needed.
All this must be stored with minimal amount of storage, i.e., you must choose the appropriate data types from the MySQL manual. You may assume that new activities will be added frequently, that activities will almost never be removed, and that the total number of distinct activities may reach 100,000.
So I already have a 'User' table with 'user_id' as my primary key.
MY SOLUTION TO THIS:
Create a table called 'Activities' and have 'activity_id' as PK (mediumint(5) ) and 'activity' as storing hobbies (varchar(80)) then I can create another table called 'Link' and use the 'user_id' FK from user table and the 'activity_id' FK from the 'Activities' table to show user with the activities that they like to do.
Is my approach to this question right? Is there another way I can do this to make it more efficient?
How would I show if one user pursues more than one activity in the foreign key table 'Link'?
Your idea is the correct, and only(?) way.. it's called a many to many relationship.
Just to reiterate what you're proposing is that you'll have a user table, and this will have a userid, then an activity table with an activityid.
To form the relationship you'll have a 3rd table, which for performance sake doesn't require a primary key however you should index both columns (userid and activityid)
In your logic when someone enters an activity name, pull all records from the activity table, check whether entered value exists, if not add to table and get back the new activityid and then add an entry to the user_activity table linking the activityid to the userid.
If it already exists just add an entry linking that activity id to the userid.
So your approach is right, the final question just indicates you should google for 'many to many' relationships for some more info if needed.