Newish to mysql DBs here. I have a table of USERS and a table of TEAMS. A user can be on more then one team. What's the best way to store the relationship between a user and what teams he's on?
Lets say there are hundreds of teams, each team consists of about 20 users, and on average a user could be on about 10 teams, also note that users can change teams from time to time.
I can think of possibly adding a column to my TEAMS table which holds a list of user ids, but then i'd have to add a column to my USERS table which holds a list of team ids. Although this might be a solution it seems messy for updating membership. It seems like there might be a smarter way to handle this information... Like another table perhaps? Thoughts?
Thanks!
ps, whats the best field type for storing a list, and whats the best way to delimit?
whats the best field type for storing a list, and whats the best way to delimit?
It's usually a really bad idea to try to store multiple values in a single column. It's hell to process and you'll never get proper referential integrity.
What you're really looking for is a join table. For example:
CREATE TABLE user_teams (
user_id INT NOT NULL FOREIGN KEY REFERENCES users(id),
team_id INT NOT NULL FOREIGN KEY REFERENCES teams(id),
PRIMARY KEY (user_id, team_id)
);
so there can be any number of team_ids for one user and any number of user_ids for one team. (But the primary key ensures there aren't duplicate mappings of the same user-and-team.)
Then to select team details for a user you could say something like:
SELECT teams.*
FROM user_teams
JOIN teams ON teams.id= user_teams.team_id
WHERE user_teams.user_id= (...some id...);
Related
I want to create a database scheme and don't really know a solution for the following scenario:
I have users, teams and projects. I want to enable to create projects as a user, but also as a team. What I thought of, was to include two foreign keys in the projects table. One for 'userId' and one for 'teamId'. But in this case for each entitiy either userId or teamId would be null.
Is this a good solution or is there a better possibility to solve that?
You can create a constraint that would force userId != null OR teamId != null.
Alternatively, you can require each project to have a non null foreign key userId (some user in the team had to actively create the project, right?), and then create an associatedTeam foreign key (which can be optional).
I am new to database designing. In my case I have to generate lot many keys per user per product. So, I have two options -
Create one table with product_id and key for all the users, or
Create a separate table for each user
In the former case I will have a single table but querying might take more time as all the entries are in the same table for all the users.
In the later case queries might return the result faster but more tables and if users cross 100 or more than it means lot of tables.
Definitely do not create a table for each user. if you create a single table for all users you can use relational database design and add specific information pertaining to each user like address or employee information and use the primary key from the users table as a foreign key. and there will not be any noticeable lag. And maintenance will be whole lot easier
if you want to build relation between your user and product then make table like below
user_product [table name]
id [Primary Key]
user_id [Reference key of user table]
product_id [Reference key of product table]
key
This is your table schema You must use.
if you generate each table then this will take more complex for database and relation management. So, just use above row base format.
if that helpful then let me know.
Thanks
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.
I want to make user group system that imitates group policy in instant messengers.
Each user can create as many as groups as they want, but they cannot have groups with duplicate names, and they can put as many friends as they want into any groups.
For example, John's friend Jen can be in 'school' group of John and 'coworker' group of John at the same time. And, it is totally independent from how Jen puts John into her group.
I'm thinking two possible ways to implement this in database user_group table.
1.
user_group (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT,
group_name VARCHAR(30),
UNIQUE KEY (user_id, group_name)
)
In this case, all groups owned by all users will have a unique id. So, id alone can identify which user and the name of the group.
2.
user_group (
user_id INT,
group_id INT AUTO_INCREMENT,
group_name VARCHAR(30),
PRIMARY KEY (user_id, group_id),
UNIQUE KEY (user_id, group_name)
)
In this case, group_id always starts from 0 for each user, so, there could exist many groups with same group_id s. But, pk pair (user_id, group_id) is unique in the table.
which way is better implementation and why?
what are advantages and drawbacks for each case?
EDIT:
added AUTO_INCREMENT to group_id in second scenario to insure it is auto-assigned from 0 for each user_id.
EDIT:
'better' means...
- better performance in SELECT/INSERT/UPDATE friends to the group since that will be the mostly used operations regarding the user group.
- robustness of database like which one will be more safe in terms of user size.
- popularity or general preference of either one over another.
- flexibility
- extensibility
- usability - easier to use.
Personally, I would go with the 1st approach, but it really depends on how your application is going to work. If it would ever be possible for ownership of a group to be changed, or to merge user profiles, this will be much easier to do in your 1st approach than in the 2nd. In the 2nd approach, if either of those situations ever happen, you would not only have to update your user_group table, but any dependent tables as well that have a foreign key relation to user_group. This will also be a many to many relation (there will be multiple users in a group, and a user will be a member of multiple groups), so it will require a separate joining table. In the 1st approach, this is fairly straightforward:
group_member (
group_id int,
user_id int
)
For your 2nd approach, it would require a 3rd column, which will not only be more confusing since you're now including user_id twice, but also require 33% additional storage space (this may or may not be an issue depending on how large you expect your database to be):
group_member (
owner_id int,
group_id int,
user_id int
)
Also, if you ever plan to move from MySQL to another database platform, this behavior of auto_increment may not be supported. I know in MS SQL Server, an auto_increment field (identity in MSSQL) will always be incremented, not made unique according to indexes on the table, so to get the same functionality you would have to implement it yourself.
Please define "better".
From my gut, I would pick the 2nd one.
The searchable pieces are broken down more, but that wouldn't be what I'd pick if insert/update performance is a concern.
I see no possible benefit to number 2 at all, it is more complex, more fragile (it would not work at all in SQL Server) and gains nothing. Remeber the groupId is without meaning except to identify a record uniquely, likely the user willonly see the group name not the id. So it doesn't matter if they all start from 0 or if there are gaps because a group was rolled back or deleted.
If I wanted to create a site that allowed users to have 0 or more "friends", how would I model such a relationship in a database? Would something this simple work:
Table Friends
- Id (PK)
- UserId (FK)
- FriendId (FK)
???
Would this allow me to later on do things like Facebook does (e.g. "3 of your friends knows this user, maybe you do too")? Or something like 6-degrees-to-Kevin-Bacon?
EDIT 1:
Table Friends
- UserId (FK)
- FriendId (FK)
- Status ('Pending', 'Approved', 'Rejected', 'Blocked'?)
This will work. Following are points to be noted:
Do you have something like friend confirmation. If yes, you will have to think on how to store 'pending'
Indexing both UserId and FriendId. These are the values on which you will be joining the tables.
The unordered pair (UserId, FriendId) is contender for Primary key.
Suppose Uid_1 and Fid_1 are friends where Uid_1 != Fid_1 then does your Friends Table store (Fid_1, Uid_1) as well as (Uid_1, Fid_1).
How far in degrees of relationship are you going to search.
Everytime you have to query for DOR(Degree of relationship) you will have to initialize a graph and run Shortest Path Algo (This is the least optimization I can think of). If your member-count rises to some kilos then how are you going to handle this?
You need many to many relationship - you can have 0 or more friends, every friend can have 0 or more friends. The most common approach is to bind both users in the additional table. You need just an additional DB table:
create table Relationships(
user1 int not null references Users(id),
user2 int not null references Users(id)
);
You definitely want to create indexes for user1 and user2.
I think you don't need the ID column. One more thing you should be aware of the thing that if I'm your friend, you are my friend to. When you insert ([u1],[u2]) into Relationships table check first if there is relationship ([u1],[u2]) or ([u1],[u2]). If there is such relationship don't insert another one, this could break your logic.
If you need some sort of confirmation like in most popular social networks you should make another table PendingRelationsihps which will have the same DB scheme as the Relationship one. After confirmation you will move the entry from pendingrelationships to relationsships.
Hope this will help you.
#devfreak is absolutely right, but I would not make a "Pending" table. It's simply redundant. The friend table can have a status field, and you can query against it based on status.