如何在SQL中查询朋友的朋友

时间:2017-11-20 13:55:09

标签: sql sql-server

我有以下架构:

我想找到一个朋友的朋友,他们的名字是" John"。这是我第一次执行这样的嵌套查询,所以我寻求帮助!

例如,我有以下数据:

calendar.add(Calendar.DATE,1);

在另一张桌子上我得到了:

|---------------------|------------------|
|      User_ID        |     Name         |
|---------------------|------------------|
|          1          |         Jon      |
|---------------------|------------------|
|          2          |         Matt     |
|---------------------|------------------|
|          3          |         Kat      |
|---------------------|------------------|
|          4          |         Sam      |
|---------------------|------------------|
|          5          |         Eli      |
|---------------------|------------------|
|          6          |         Kay      |
|---------------------|------------------|

查询的结果是具有ID&#39的用户的姓名:

|---------------------|------------------|------------------|
|  User_friend_ID     |     user_id      |     friend_id    | 
|---------------------|------------------|------------------|
|          1          |         1        |        2         | 
|---------------------|------------------|------------------|
|          2          |         2        |        3         | 
|---------------------|------------------|------------------|
|          3          |         3        |        4         | 
|---------------------|------------------|------------------|
|          4          |         4        |        2         | 
|---------------------|------------------|------------------|
|          5          |         4        |        3         | 
|---------------------|------------------|------------------|
|          6          |         4        |        5         | 
|---------------------|------------------|------------------|

3 个答案:

答案 0 :(得分:2)

从查询朋友(f0)开始:

select friend.*
from User friend
join Friends f0 on friend.user_id=f0.friend_id
where f0.user_id=my_user_id

通过添加第二个联接来扩展它以成为朋友的朋友f1

select friend.*
from User friend
join Friends f1 on friend.user_id=f1.friend_id
join Friends f0 on f1.user_id=f0.friend_id
where f0.user_id=my_user_id

将第三个联接添加到f2会给你一个朋友的朋友。您应该可以通过以上两个示例完成本练习。

答案 1 :(得分:2)

这应该有效:

SELECT ff.user_id, uf.name FROM [User] u
INNER JOIN [Friends] f ON u.user_id = f.user_id --= to find his friends
INNER JOIN [Friends] ff ON f.friend_id = ff.user_id --= f.friend_id is his friends
INNER JOIN [User] uf ON ff.friend_id = uf.user_id --= ff.friend_id is friends of his friends
WHERE u.name = 'John'
GROUP BY ff.user_id,uf.name

选择朋友的朋友的id以及他的名字。

答案 2 :(得分:2)

@Juan Romero和@dasblinkenlight已经给出了很好的答案。如果需要,下面是几个更复杂的选项。即允许您轻松地在朋友的朋友之间切换到没有重新编码的朋友的朋友的朋友,并且在他们'的地方排除朋友的朋友。也是朋友的朋友。

declare @userId long = 1 --whichever user's friends you're looking for
, @degreesOfSeparation = 3 --friend of a friend of a friend
, @name nvarchar(32) = 'John'

; with relationshipCte as 
(

    --get our patient 0 (the user whose friends we're looking for)
    select 0 degreesOfSeperation
    , user_id
    from [user]
    where user_id = @userId

    full outer join 

    --for every friend, pull back that friend's friends
    select degreesOfSeperation + 1
    , friend_id
    from relationshipCte cte
    inner join [Friends] f 
        on f.user_id = cte.user_id
        --and not f.friend_id = @userId --include this if we want to exclude the original user as being a friend of a friend (and similar)

)
select *
from relationshipCte cte
inner join [user] u
on u.user_id = cte.user_id
where cte.degreesOfSeperation = @degreesOfSeperation
and u.Name = @name
order by u.user_id
option (maxrecursion 10) --never go more than 10 relationships away from patient 0 (arguably a reasonable assumption given https://en.wikipedia.org/wiki/Six_degrees_of_separation)

如果你想避免包括任何超过3度分离的朋友(例如你和Jim和Jane是朋友; Jim和Jane是彼此的朋友;他们是朋友,也是朋友朋友们),使用下面的内容:

declare @userId long = 1 
, @degreesOfSeparation long = 3
, @i long = 1
, @name nvarchar(32) = 'John'

declare @relationships table 
(
    user_id long
    , closestRelation long
)
insert @relationships (user_id, closestRelation) values (@userId, 0) --insert patient 0
while @i <= @degreesOfSeperation
begin
    insert @relationships (user_id, closestRelation) --insert friends
    select f.friend_id, @i
    from @relationships
    inner join Friends f
    on f.user_id = u.user_id
    where not exists (select top 1 1 from @relationships r where r.user_id = f.friend_id) --exclude friends already in our list
   SET @i = @i + 1
end

select *
from @relationships r
inner join [user] u
on u.user_id = r.user_id
where r.closestRelation = @degreesOfSeperation
and u.Name = @name
order by u.user_id

注意:我没有机会运行上面的SQL;但希望应该按照规定工作......