I'm creating a db schema that involves users that can be friends, and I was wondering what the best way to model the ability for these friends to have friendships. Should it be its own table that simply has two columns that each represent a user? Thanks!
+2
A:
Yes (use a n:m link table).
You have two entities:
- user (for User-Data like ID, Name, email etc.)
- relationship (links two users by ID)
create one table each.
lexu
2010-05-26 06:05:27
+3
A:
create table
friendship(
user bigint,
friend bigint,
primary key(user, friend),
key(friend, user),
constraint `fk_user` foreign key (user) references user(id),
constraint `fk_friend` foreign key (friend) references user(id)
);
When user 1 sends a friendship request to user 2, do
insert into friendship (user, friend) values (1,2);
If user 2 denies the request,
delete from friendship where user = 1 and friend = 2;
if user 2 accepts it:
insert into friendship (user, friend) values (2,1);
Then, a friendship can be found this way:
select f1.*
from friendship f1
inner join friendship f2 on f1.user = f2.friend and f1.friend = f2.user;
You can make a view with this last query, it will help you query-ing for users' friends, or even friends of friends.
ceteras
2010-05-26 09:24:53
+1 for this straight and detailed answer. However, I try to balance pros and cons for one row vs. two rows per friendship. Could you explain why two rows are better in your opinion?
Tim Büthe
2010-05-28 14:11:20
Good question. I use the above structure in a legacy application, but if I was to implement one, I'd give it a try with one-row structure.If you have `user`, `friend` and `status` columns for a friendship (where status could mean pending, accepted, rejected or deleted), it would be a lot easier to query for pending requests (with two-rows you need a left join).However, querying for an user's friends would be more difficult:`select case when user=@userId then friend else user end as friendIdfrom friendship where (user=@userId or friend=@userId) and status = 1;`
ceteras
2010-05-31 12:57:41