Is there an elegant way to store a dual relationship (i.e. user 1 and user 2 are friends)

荒凉一梦 提交于 2019-11-29 02:34:10

There is also a way to use the 2nd approach by adding an extra constraint. Check that u1 < u2:

CREATE TABLE User
( Name VARCHAR(10) NOT NULL
, PRIMARY KEY (Name)
) ;

CREATE TABLE MutualFriendship
( u1 VARCHAR(10) NOT NULL
, u2 VARCHAR(10) NOT NULL
, PRIMARY KEY (u1, u2)
, FOREIGN KEY (u1) 
    REFERENCES User(Name)
, FOREIGN KEY (u2) 
    REFERENCES User(Name)
, CHECK (u1 < u2) 
) ;

The rules to read, create, insert or update will have to use the (LEAST(u1,u2), GREATEST(u1,u2)).

In SQL it's easy to implement the constraints to support your first approach:

CREATE TABLE MutualFriendship
(u1 VARCHAR(10) NOT NULL,
 u2 VARCHAR(10) NOT NULL,
 PRIMARY KEY (u1,u2),
 FOREIGN KEY (u2,u1) REFERENCES MutualFriendship (u1,u2));

INSERT INTO MutualFriendship VALUES
('Alice','Bob'),
('Bob','Alice');

For anyone that's interested, I played around with a few bitwise operations and found that the following seems to fulfill the criteria for f(x,y):

#Python, returns 3 tuple
def get_hash(x, y):
  return (x & y, x | y, x * y)

I can't prove it, though.

"x is a friend of y".

Define a table of (x,y) pairs and enforce a canonical form, e.g. x<y. This will ensure that you cannot have both (p,q) and (q,p) in your database, thus it will ensure "store once".

Create a view as SELECT x,y FROM FRIENDS UNION SELECT x as y, y as x FROM FRIENDS.

Do your updates against the base table (downside : updaters must be aware of the enforced canonical form), do your queries against the view.

You seem to limit the number of friends to 1. If this is the case then I would use something like u1,u2 u2,u1 u3,null u4,u5 u5,u4

u3 does not have a friend.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!