代码之家  ›  专栏  ›  技术社区  ›  Sergey Kozlov

PostgreSQL排除了已经存在的友谊关系

  •  0
  • Sergey Kozlov  · 技术社区  · 7 年前

    我有两张桌子: 用户 友谊 :

    CREATE TABLE t_users (
    user_id varchar PRIMARY KEY,
    name varchar
    );
    
    CREATE TABLE t_friendship (
    friendship_id varchar PRIMARY KEY,
    from_user_id varchar,
    to_user_id varchar
    );
    
    INSERT INTO t_users VALUES ('us123', 'us123');
    INSERT INTO t_users VALUES ('us456', 'us456');
    INSERT INTO t_users VALUES ('us789', 'us789');
    INSERT INTO t_users VALUES ('us987', 'us987');
    INSERT INTO t_users VALUES ('us654', 'us654');
    INSERT INTO t_users VALUES ('us321', 'us321');
    
    INSERT INTO t_friendship VALUES ('fr123', 'us123', 'us456');
    INSERT INTO t_friendship VALUES ('fr456', 'us123', 'us789');
    INSERT INTO t_friendship VALUES ('fr789', 'us123', 'us987');
    INSERT INTO t_friendship VALUES ('fr987', 'us456', 'us123');
    INSERT INTO t_friendship VALUES ('fr654', 'us456', 'us321');
    INSERT INTO t_friendship VALUES ('fr321', 'us987', 'us123');
    INSERT INTO t_friendship VALUES ('fr322', 'us456', 'us654');
    INSERT INTO t_friendship VALUES ('fr323', 'us654', 'us123');
    INSERT INTO t_friendship VALUES ('fr324', 'us789', 'us654');
    INSERT INTO t_friendship VALUES ('fr325', 'us321', 'us123');
    
    SELECT 
    t_users.user_id, 
    t_users.name
    FROM  t_friendship
    inner join t_users on t_friendship.from_user_id = t_users.user_id
    WHERE t_friendship.to_user_id = 'us123';
    

    Work example

    如何提出将显示推荐朋友的请求,同时 不包括 已经 现有的 友谊关系(从用户ID->到用户ID)?例如 'US123'、'US456' .

    谢谢您。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Gordon Linoff    7 年前

    对于您的特定结果,您将使用:

    select u.*
    from t_users u
    where not exists (select 1
                      from t_friendships f
                      where f.to_user_id = 'us123' and
                            f.from_user_id = u.user_id 
                     ) and
          u.user_id <> 'us123';
    

    SQL小提琴是 here .

    更常见的是,友谊是对称的——也就是说,如果A/B是朋友,那么B/A也是。如果这个一般规则是正确的,那么可以这样做:

    选择U.。*
    从T用户U
    如果不存在(选择1
    从你的友谊F
    其中f.to_user_id='us123'和
    f.from_user_id=u.user_id
    )
    u.user_id<>'us123';
    

    如果你想排除朋友向任何一个方向提出的建议,请使用 not exists 两次:

    select u.*
    from t_users u
    where not exists (select 1
                      from t_friendships f
                      where f.to_user_id = 'us123' and
                            f.from_user_id = u.user_id 
                     ) and
          not exists (select 1
                      from t_friendships f
                      where f.from_user_id = 'us123' and
                            f.to_user_id = u.user_id 
                     ) and
          u.user_id <> 'us123';
    

    此查询不会返回任何行,因为用户与所有其他用户有朋友(在某些方向)。

    注意,如果您是从应用程序调用这个函数,那么您应该使用参数,而不是将用户ID填充到查询字符串中。