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

前端 未结 5 1094
野趣味
野趣味 2020-12-16 06:01

I\'ve run into the same problem in two different pieces of work this month:

Version 1: User 1 & User 2 are friends
Version 2: Axis 1 & Axis 2 when gr         


        
相关标签:
5条回答
  • 2020-12-16 06:39

    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.

    0 讨论(0)
  • 2020-12-16 06:46

    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)).

    0 讨论(0)
  • 2020-12-16 06:56

    "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.

    0 讨论(0)
  • 2020-12-16 06:58

    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.

    0 讨论(0)
  • 2020-12-16 07:01

    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');
    
    0 讨论(0)
提交回复
热议问题