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

时间:2018-07-22 12:58:50

标签: sql postgresql

我有两个表:用户友谊

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

如何发出显示推荐朋友的请求,同时排除已经存在的友谊关系(from_user_id-> to_user_id)?例如'us123','us456'

谢谢。

1 个答案:

答案 0 :(得分:1)

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

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 Fiddle是here

更常见的是,友谊是对称的-也就是说,如果a / b是朋友,则b / a也是如此。如果该一般规则成立,则可以执行以下操作:

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';

如果要避免在任何一个方向上提出朋友建议,请两次使用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填充到查询字符串中。