首页 > 解决方案 > 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';

工作示例

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

谢谢你。

标签: sqlpostgresql

解决方案


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

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 在这里

更常见的是,友谊是对称的——这意味着如果 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 填充到查询字符串中。


推荐阅读