I'm creating a website and users can add friends. I want them to be able to see their personal friends on a page.
For exemple:
John add user Tim and Bill.
When John goes on his friends list page, I want him to be able to see that he has Tim and Bill. How do I do that? Is that even possible? Do I need more than one table? If so, does every user has to have his own friendsList table?
Yes this is possible, you do this by querying the information from the database, the answer for if you need multiple tables etc all depends on your current table structure but at the very least you need to have some way of referencing that a Person 'John' has friends, wether thats just a 'friendID' in the same 'Person' table, or another means of doing so. then it is just a matter of querying the data correctly to return what you want and bind to the websites fields :D
One way of defining the structure is the following:
Person
PersonId
Name
<other person fields>
Relationship
RelationshipId
Name --> allow to define multiple relation types like Friendship, Follows etc.
Relationship
RelationshipId
Person1Id --> FK to Person
Person2Id --> FK to Person
RelationshipTypeId --> FK Relationship
Basically, you use an n:n between Persons (anyone can have any number of friends) and also allow for other types of relationships.
Assuming you already have a table of users, one approach would be to create a "friends" table which relates users to other users.
CREATE TABLE friends (
`user_id` INT NOT NULL,
`friend_id` INT NOT NULL
);
Both user_id and friend_id would have foreign key constraints on your existing users table (so that you guarantee an id must exist in your user table in order for it to exist in the friends table as either a user_id or friend_id).
You can then link your user table on users.id = friends.friend_id to get the friend's info.
Here is a SQL Fiddle Demo showing how this works.
You should consider using an ON DELETE CASCADE constraint on the friends table, so that if a user is deleted from the user table, the associated records in the friends table are also deleted.
Related
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 am using DBDesigner 4 for designing my database relations.
I have a users table and a recipes table. One user can own many recipes but one recipe cannot be owned by many users. This relationship is shown by the user_recipes relation in the picture. (A one-to-many relationship from users to recipes).
However, recipes can be liked by users. Many users can like many recipes. This is a many-to-many relationship between users and recipes and the pivot table for this is users_like_recipes.
But when I create this pivot table, I only need the users_id and recipes_id column. The recipes_users_id column is getting added on its own and I am not able to remove it. It says the third column has come from another Relation which is defined in the model. I guess its the user_recipes relation.
When I remove the user_recipes relation, I get the pivot table like I want to.
But I need the user_recipes relation too!
Please. Any help would be appreciated.
I would suggest removing user_id as a primary key from from the recipes table. Currently the combination if id and user_id provides identification for your recipes table. In this situation multiple user_id's can create the same recipe id because the combination has to be unique. user_id can just be a normal column in your table. If you REALLY want to, you can make an alternate key on (id, user_id) but you do not need it because the id is unique.
I have two tables. "users" and "movies". Users table consists of "id"(Auto increment), "name" and "password" columns. There are 2 usernames stored right now. In movies table there are 'title' and 'year' columns. The PHP script allows each user to watch and add new movies to their list. How do I link or make the parent-child relationship or whatever is needed to make it happen in MySQL? Oh, and I also use Adminer. Right now when I log in one user I still see the same movies that I've added with the other user.
If you are stuck with using just two tables as stated in a comment, you have to redesign the Movies table to include a column UserID which identifies which user created that entry. Then you can filter the data so that a user only sees information about the movies they added to the list.
This isn't a good design — the answer by Jeremy Smyth suggesting an extra table to relate movies to users is much more sensible, but you've indicated that isn't allowed. The reason it isn't a good design is that you're going to end up with lots of rows indicating that the same movie was released in the same year, each row entered by a different user, so there is unnecessary repetition. There's also more chance for error; you'll get entries for 'Gone With The Wind' 1938, and 'Gone With The Wind' 1939, and 'Gone With The Wind' 1940 when there should only be one year (1939, as it happens).
Can you please be more specific about what I have to do ...
In the two-tables-only system, you would create the Movies table like this:
CREATE TABLE Movies
(
Title VARCHAR(32) NOT NULL,
Year INTEGER NOT NULL,
UserID INTEGER NOT NULL REFERENCES Users(ID),
PRIMARY KEY(Title, Year, UserID)
);
When you insert a record into this table, you record the ID of the user who did the insertion, so you can query who created which movie records.
If you are actually going to reference this table from elsewhere in the database, you might well add an ID column here, but if there are more tables, then you'd drop the UserID column from this table and create a relationship table:
CREATE TABLE Movies
(
ID INTEGER AUTOINCREMENT PRIMARY KEY,
Title VARCHAR(32) NOT NULL,
Year INTEGER NOT NULL,
UNIQUE(Title, Year)
);
CREATE TABLE Users_Movies
(
MovieID INTEGER NOT NULL REFERENCES Movies(ID),
UserID INTEGER NOT NULL REFERENCES Users(ID),
PRIMARY KEY(MovieID, UserID)
);
Now you can have one record for 'Gone With The Wind' 1939, which might have ID number 207, and twenty different people might list MovieID 207 as one of their movies with 20 simple records in the Users_Movies table.
You will need to create a "many-to-many" relationship between your two tables.
To do this:
First, create an ID column in the Movies table to uniquely identify each one
Then, create another table called user_movies (or "watched" or something useful), that contains the user ID, the movie ID, and any other information you wish to add such as date watched or rating (number of "stars") etc.
Then, whenever a user watches a movie, add a record to the user_movies table to mark the fact that they've done it.
It should be many-to-many, because each user can watch several movies, but each movie can be watched by several users. A "parent-child" relationship isn't appropriate in this case, being a one-to-many relationship.
I want two tables to share a primary auto incrementing id, is this possible? how do i do this? is their anything i need to consider?
the reasons i am doing this, is because it is a better solution than adding groups column to the users table, and also better than creating a completly seperate groups table, because if they share a primary key, i can use the existing posts table for both groups and users. instead of having to create a two distinct posts tables, (group_posts table for group posts. and a user_posts table for user posts.)
existing users table is
id(primary, ai)
username
password
email
my groups table that i want to link to my users table with a shared ai primary key
id(primary, ai, linked to users table id)
group_name
created_by
creation_date
etc.
You should make you schema clearer by doing the following:
Create a table (e.g. people)
id, primary key, auto-increment
type, tells you if it's a user or a group
Make users and groups primary keys foreign keys on people
Insert records in people
Obtain the ID that was assigned using LAST_INSERT_ID()
Insert in users or groups appropriately, using the ID obtained above
Then you'd reference "people", and not "users" or "groups" in your posts table and so on.
Conceptually, thinking of it in an OO way, it means users and groups both extend people.
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.