views:

108

answers:

2

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
+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
+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
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