如何在pgsql中获得朋友的朋友
我正在创建一个友谊模型模式 这是表的结构如何在pgsql中获得朋友的朋友,sql,postgresql,Sql,Postgresql,我正在创建一个友谊模型模式 这是表的结构 --PostgreSQL 9.6 --'\\' is a delimiter create table user_list( id bigserial primary key, first_name text not null, last_name text, avatar_url text ); create table friendship ( id bigserial primary key,
--PostgreSQL 9.6
--'\\' is a delimiter
create table user_list(
id bigserial primary key,
first_name text not null,
last_name text,
avatar_url text
);
create table friendship (
id bigserial primary key,
user_id bigint not null,
friend_user_id bigint not null,
CONSTRAINT fk_friend1
FOREIGN KEY(user_id)
REFERENCES user_list(id),
CONSTRAINT fk_friend2
FOREIGN KEY(user_id)
REFERENCES user_list(id)
);
还有一些记录
insert into user_list(id,first_name,last_name,avatar_url) values(1,'Sunny',null,null),(2,'Dev',null,null),(3,'Ram',null,null),(4,'Prinka',null,null),
(5,'Neha',null,null);
insert into friendship(id,user_id,friend_user_id) values(1,1,3),(2,1,2),(3,2,3),(4,2,5),(5,5,1);
所以友谊表维持着这种关系。如果user1是user2的朋友,我们将在友谊表user1、user2中插入一条记录
这表示user1是user2的朋友,反之亦然
所以通过搜索user2的友谊,应该返回user1
查询以获取用户的朋友此操作正常
-- get frieds of user
SELECT distinct(u.id) as friend_id,u.first_name FROM friendship AS f , user_list AS u WHERE
CASE WHEN f.user_id = 1 THEN f.friend_user_id = u.id WHEN
f.friend_user_id = 1 THEN F.user_id = u.id END;
现在,如果我想获得用户朋友的朋友,我正在尝试这个嵌套查询
-获取好友的好友好友用户的共同好友
SELECT distinct(t.friend_id) as friend_id,t.first_name FROM
(SELECT distinct(u.id) as friend_id,u.first_name FROM friendship AS f , user_list AS u WHERE
CASE WHEN f.user_id = 1 THEN f.friend_user_id = u.id WHEN
f.friend_user_id = 1 THEN F.user_id = u.id END) as t,friendship as f2
where
CASE WHEN f2.user_id = t.friend_id THEN f2.friend_user_id = t.friend_id WHEN
f2.friend_user_id = t.friend_id THEN f2.user_id = t.friend_id END;
连我都试过了
SELECT DISTINCT u3.friend_user_id FROM friendship u1
JOIN friendship u2 ON u1.friend_user_id = u2.user_id
JOIN friendship u3 ON u2.friend_user_id = u3.user_id
WHERE u1.user_id = 1;
但这两个查询都不起作用。有什么帮助吗
还有没有其他方法可以通过优化的方式获得用户的朋友
这里是在线pgsql工具,可以尝试一下
我认为这可以通过一个联合和一些情况来实现,但是我建议在友谊表中始终存储2条记录,如果用户1是用户2的朋友,那么应该有记录1,2和2,1 此查询还可以包括直接朋友,因为朋友的朋友也可以是直接朋友 解释 查询分为两部分,让我们参加第1部分:
select distinct case when f1.friend_user_id = f2.user_id then f2.friend_user_id
when f1.friend_user_id = f2.friend_user_id then f2.user_id
from friendship f1
left join friendship f2
on f1.friend_user_id = f2.user_id
or f1.friend_user_id = f2.friend_user_id
where f1.user_id = 1
这将获得所有友谊f1,其中用户1要求其他用户成为朋友,即1,2,1,3,但不是5,1。然后我们再次加入友谊表,参考f2,以获得朋友的朋友。朋友的朋友由f1.friend\u user\u id=f2.user\u id加入,或由f1.friend\u user\u id=f2.user\u id加入。这将得到2,5
第2部分的工作方式相同,只是从要求用户1成为朋友的用户开始,即5,1,并从何处开始
同样,如果始终两个条目都可以表示,那么整个查询可以大大简化,因此1,2和2,1。下面的递归cte应该为您完成这项工作
with recursive cte as
(
select ul.id, fd.friend_user_id from friendship fd
join user_list ul on ul.id=fd.user_id
where ul.id = 1
union all
select ul.id, fd.friend_user_id from friendship fd
join cte on cte.friend_user_id = fd.user_id
join user_list ul on ul.id=fd.user_id
where fd.friend_user_id <>1
)
select distinct friend_user_id from cte
您可以阅读有关递归cte的更多信息
递归cte可能会进入无限循环,请确保您添加了条件以避免出现这种情况,就像我添加了fd.friend\u user\u id 1一样。您可以解释查询吗?添加了解释吗
with recursive cte as
(
select ul.id, fd.friend_user_id from friendship fd
join user_list ul on ul.id=fd.user_id
where ul.id = 1
union all
select ul.id, fd.friend_user_id from friendship fd
join cte on cte.friend_user_id = fd.user_id
join user_list ul on ul.id=fd.user_id
where fd.friend_user_id <>1
)
select distinct friend_user_id from cte