Database Design: User can be part of many lists, and lists can be associated with multiple users - mysql

So I'm trying to work on a small app that would allow you to have a grocery list that can be edited by multiple people via their mobile phone. So I'm trying to design the database I will use on the backend. I'm having trouble figuring out how to relate all the tables. User will be able to be apart of multiple lists, and each list will be accessible by multiple people. ( I believe this is called a many-to-many relationship?)
So far my tables look as follows:
User(id, name)
List(id, Name)
List_item(id, List_id(key), name, amount)
The list to list_item ID relationship is easy enough, but how do I go about modelling the relationship between Users and Lists? Do I need a separate join table:
User-to-List(User ID,List ID)
I'm trying to come up with the most efficient structure as possible, Thanks!
Edit: Only the user needs to know about all the lists he is associated with, the list doesn't need to keep track which user are associated with it. At least for the initial app!

Many-to-many:
CREATE TABLE ListsUsers (
list_id ...,
user_id ...,
PRIMARY KEY(list_id, user_id),
INDEX(user_id, list_id)
) ENGINE=InnoDB;
Then use suitable JOINs to connect the tables when doing a SELECT.

Related

Effect of more tables on database efficiency SQL

I am currently attempting to create a chat program aimed for 1000-1500 users. I was wondering if i should create a separate table for each user, as in a table for each users friends, message or should just create one include all table and store everything there, as in which solution would be more efficient? I believe having multiple tables for each users personal details would be more efficient so that most queries i run are run on tables with small amount of data.
Could anyone tell me if i am wrong?
You are very wrong. Ideal way should be to have one single table for users. Even for companies like ebay where there are millions of users; the way those users are distributed are like all users starting with A in a single table ... As #Matt mentioned we cannot create tables where x is not a bounded number.
Along with that table you can have a table Messages which will have a column UserName which will be a foreign key pointing to your user table.
Cleanest possible solution can be a bit tricky for maintaining friends list. A workaround solution can be to have a column in User table which will have comma separated ids of Friends ( which are again users in same table ). If you do not want any limits on friends list: You could just create another table Friends having two columns userid, friendId. Both these columns will be foreign keys on User table. Now, query will be simple select * form Friends where userid=<user> . This table might be huge; but that is where index comes into picture. You can create an index on userid column and query results will be super fast even with lots of records.
Its a bad approach to set a table for each user, you can exactly save a text file for each user, you dont need a database for that, the idea of using a ddatabase is build the relations between the entities, therefor you have the primary/foreign keys, in general you need a table for each entity, sometimes 3 tables for 2 entities depending on the Cardinality. In your would be normal to have for example a user table, messages table, messageUser table and freinds or contacts table etc, where the freinds one would store the UserIds whos connected as freinds , and the messages one the messageId<->UserId tuple which matches the messages to the user and so on.

Designing a schema for players and tournaments

I am beginner in SQL, I have a simple MySQL database which contains two tables:
Players (id, name)
Tournaments (id, name, participants)
I want to save information about participants of every tournament. The first idea that I have is that participants should contain a large number of id fields from the players table but that doesn't seem good.
How should I design this in the correct way?
Make another table called Participants with two fields. Player_ID and Tournament_ID. This table can hold as many lines as it needs to to correlate who played when, and you can cross reference it as needed.
Remove "participants" from the second table and add a third table: TournamentPlayers (playerid, tournamentid).
You should avoid storing multiple values in one field. That would break the first normal form of database design (1NF), which states that only atomic values can be stored in one field. Relational database systems are not well-suited to cope with non-normalized data, and you will have a hard time writing queries for non-1NF tables.

Model a table that can have a relationship with several tables

I have a table called 'notes', on this table I need to track who made that note, but the problem is that the creator of the note can be a user stored in one of three possible tables:
users
leads
managers
I have though of simply create three fields on 'notes' to represent the three possible relations: note.user, note.lead, note.manager
With this approach I would be forced to create three table joins when requesting the notes to gather the creators information, and I don't think that is the way to go, so I would like to hear your ideas or comments and what would be the best approach on this.
For me personally this smells like a design problem on a totally different part of the schema: Are manageers not users? Do leads carry person information?
With any approach that creates a relation between one column and one of three others, you will need three joins for the select. If you can't rectify the underlying problem, I recommend you use
note_type ENUM('users','leads','managers')
as an additional field and
SELECT
...
IFNULL(users.name(IFNULL(managers.name,leads.name))) AS name
..
FROM notes
LEFT JOIN users ON notes.note_type='users' AND users.id=notes.note_source
LEFT JOIN managers ON notes.note_type='managers' AND managers.id=notes.note_source
LEFT JOIN leads ON notes.note_type='leads' AND leads.id=notes.note_source
...
for the query
I think you need to abstract out the concept of a user id, so that it does not depend on their role. The author of a note could then be specified by the user id.
Users could be assigned roles, and maybe more than one.
The correct way to structure this would be to pull all common data out of users, leads, and managers. Unify this data into a "contact" table. Then if you want to get all notes for a given manager:
managers->contacts->notes
for a lead:
leads->contacts->notes
Notice your original post: "the problem is that the creator of the note can be a user stored in one of three possible tables"
From the structure of your sentence you even admit that all these entities have something in common; they are all users. Why not make the DB reflect this?
you have to model a parent table for the three tables you already have. Define a table that depicts generally user, leads and manager tables. Something like "Person". So you have all of the ids of the three tables and any common attributes on the Person table. And when you must define the relationship you put the foreign id "Person_ID" on the note table. And when you model user, leads and manager tables you also put the primary key as a foreign key to the Person table.
So you would have something like this:
Table users:
Users(
person_id primary key
...(attributes of Users)
foreign key person_id references Person.person_id
)
This model i depict is common to any relational model you have to model using parents and childs

Users table - one table or two?

i wanna have a Users details stored in the database.. with columns like firstname, last name, username, password, email, cellphone number, activation codes, gender, birthday, occupation, and a few other more. is it good to store all of these on the same table or should i split it between two users and profile ?
If those are attributes of a User (and they are 1-1) then they belong in the user table.
You would only normally split if there were many columns; then you might create another table in a 1-1 mapping.
Another table is obviously required if there are many profile rows per user.
One table should be good enough.
Two tables or more generally vertical portioning comes in when you want to scale out. So you split your tables in multiple tables where usually the partiotioning criteria is the usage i.e., the most common attributes which are used together are housed in one table and others in another table.
One table should be okay. I'd be storing a hash in the password column.
I suggest you read this article on Wikipedia. about database normalization.
It describes the different possibilities and the pros and cons of each. It really depends on what else you want to store and the relationship between the user and its properties.
Ideally one table should be used. If the number of columns becomes harder to manage only then you should move them to another table. In that case, ideally, the two tables should have a one-one relationship which you can easily establish by setting the foreign key in the related table as the primary key:
User
-------------------------------
UserID INT NOT NULL PRIMARY KEY
UserProfile
-------------------------------------------------------
UserID INT NOT NULL PRIMARY KEY REFERENCES User(UserID)
Depend on what kind of application it is, it might be different.
for an enterprise application that my users are the employees as well, I would suggest two tables.
tbl_UserPersonallInformation
(contains the personal information
like name, address, email,...)
tbl_UserSystemInformation (contains
other information like ( Title,
JoinedTheCompanyOn,
LeftTheCompanyOn)
In systems such as "Document Managements" , "Project Information Managements",... this might be necessary.
for example in a company the employees might leave and rejoin after few years and even they will have different job title. The employee had have some activities and records with his old title and he will have some more with the new one. So it should be recorded in the system that with which title (authority) he had done some stuff.

What's the best approach to designing a database that keeps track of orders and wish lists?

The best way to describe this scenario is to use an example. Consider Netflix: do they
store their orders (DVD's they mail out) in a separate table from their member lists (NOT members table, but a joiner table of members and movies--a list of movies each member has created), or are orders distinguished by using additional information in the same row of the same table?
For those not familiar with Netflix, imagine a service that lets you create a wish list of movies. This wish list is subsequently sent to you incrementally, say two movies at a time.
I would like to implement a similar idea using a MySQL database, but I am unsure whether to create two tables (one for orders and one for lists) and dynamically move items from the lists table to the orders table (this process should be semi-automatic based on the member returning an item, where before a new one is sent out, a table with some controls will be checked to see if the user is still eligible/has not gone over his monthly limit)...
Thoughts and pros and cons would be fantastic!
EDIT: my current architecture is: member, items, members_items, what I am asking is if to store orders in the same table as members_items or create a separate table.
Moving things from one database table to another to change its status is simply bad practice. In a RDBMS, you relate rows from one table to other rows in other tables using primary and foreign key constraints.
As for your example, I see about four tables just to get started. Comparing this to Netflix, the grand-daddy of movie renting, is a far-cry from reality. Just keep that in mind.
A User table to house your members.
A Movie table that knows about all of the available movies.
A Wishlist or Queue table that has a one-to-many relationship between a User and Movies.
An Order or Rental table that maps users to the movies that are currently at home.
Statuses of the movies in the Movie table could be in yet another table where you relate a User to a Movie to a MovieStatus or something, which brings your table count to 6. To really lay this out and design it properly you may end up with even more, but hopefully this sort of gives you an idea of where to begin.
EDIT: Saw your update on exactly what you're looking for. I thought you were designing from scratch. The simple answer to your question is: have two tables. Wishlists (or member_items as you have them) and Orders (member_orders?) are fundamentally different so keeping them separated is my suggestion.
A problem with storing orders in the members table is that there's a variable number (0, 1, or several) of orders per member. The way to do this using a relational database is to have two separate tables.
I feel like they would store their movies as follows (simplified of course):
tables:
Titles
Members
Order
Order_Has_Titles
This way an order which has a foreign key to the Members would then have a pivot table as many orders could have many titles apart of them.
When you have a many to many realtionship in the database you then need to create a pivot table:
Order_Has_Titles:
ID (auto-inc)
Order_FkId (int 11)
Title_FkId (int 11)
This way you're able to put multiple movies apart of each order.
Of course this is simplified, and you would have many other components which would be apart of it, however at a basic level, you can see it here.