希望mysql查询找到两个朋友之间的共同朋友但是 我以前的单向关系保持用户的友谊。
首先是用户表
id name
1 abc
2 xyz
3 pqr
现在第二张桌子是朋友
id user_id friend_id
1 1 2
2 1 3
3 2 3
现在我可以说abc(id = 1)是xyz(id = 2)的朋友,现在类似于xyz是abc的朋友,但现在我想找到abc(id = 1)和xyz之间的共同朋友(id = 2)那是pqr所以我想要mysql查询。
答案 0 :(得分:2)
<强> REVISED 强>
此查询将把friend表中某行的“单向”关系视为“双向”关系。也就是说,它会考虑朋友关系:('abc','xyz')
等同于反向关系:('xyz','abc')
。 (注意:我们不保证两行都不会出现在表格中,因此我们需要注意这一点。UNION
运算符可以方便地为我们删除重复项。)
此查询应符合规范:
SELECT mf.id
, mf.name
FROM (
SELECT fr.user_id AS user_id
, fr.friend_id AS friend_id
FROM friend fr
JOIN users fru
ON fru.id = fr.user_id
WHERE fru.name IN ('abc','xyz')
UNION
SELECT fl.friend_id AS user_id
, fl.user_id AS friend_id
FROM friend fl
JOIN users flf
ON flf.id = fl.friend_id
WHERE flf.user IN ('abc','xyz')
) f
JOIN users mf
ON mf.id = f.friend_id
GROUP BY mf.id, mf.name
HAVING COUNT(1) = 2
ORDER BY mf.id, mf.name
SQL Fiddle here http://sqlfiddle.com/#!2/b23a5/2
下面给出了我们如何达到这一点的更详细解释。下面的原始查询假设朋友表中的一行表示“单向”关系,因为“'abc' ff 'xyz'
”并不表示“'xyz' ff 'abc'
”。但OP的其他评论暗示情况并非如此。
如果friend(user_id,friend_id)
上有唯一约束,那么获得结果的一种方法是获取每个用户的所有朋友,并获得该朋友的行数。如果计数为2,那么我们知道用户'abc'和'xyz'都会显示特定的friend_id
SELECT mf.id
, mf.name
FROM friend f
JOIN users uu
ON uu.id = f.user_id
JOIN users mf
ON mf.id = f.friend_id
WHERE uu.name IN ('abc','xyz')
GROUP BY mf.id, mf.name
HAVING COUNT(1) = 2
ORDER BY mf.id, mf.name
(此方法还可以扩展为通过在IN列表中包含更多用户,并更改我们将COUNT(1)与之比较的值来查找三个或更多用户的共同朋友。
这不是唯一会返回指定结果集的查询;还有其他方法可以获得它。
获得等效结果的另一种方法:
SELECT u.id
, u.name
FROM ( SELECT f1.friend_id
FROM friend f1
JOIN users u1
ON u1.id = f1.user_id
WHERE u1.name = 'abc'
) t1
JOIN ( SELECT f2.friend_id
FROM friend f2
JOIN users u2
ON u2.id = f2.user_id
WHERE u2.name = 'xyz'
) t2
ON t2.friend_id = t1.friend_id
JOIN users u
ON u.id = t1.friend_id
ORDER BY u.id, u.name
备注强>
这些查询不检查用户'abc'是否是'xyz'的朋友(WHERE子句中指定的两个用户名)。它只找到'abc'和'xyz'的共同朋友。
<强>后续强>
上述查询满足指定的要求,以及问题中提供的所有示例和测试用例。
现在听起来好像你希望那个关系表中的一行被认为是“双向”关系,而不仅仅是“单向”关系。听起来你想要考虑相当于('xyz','abc')的朋友关系('abc','xyz')。
要实现这一点,那么所有需要做的就是让查询创建反向行,这样可以更容易查询。我们只需要小心,如果这些行('abc','xyz')和('xyz','abc')已经存在,那么当我们反转它们时,我们不会创建它们的重复。
要创建反向行,我们可以使用这样的查询。 (当我们没有JOIN到users表时,查看这个更简单,我们只使用id值:
SELECT fr.user_id
, fr.friend_id
FROM friend fr
WHERE fr.user_id IN (1,2)
UNION
SELECT fl.friend_id AS user_id
, fl.user_id AS friend_id
FROM friend fl
WHERE fl.friend_id IN (1,2)
如果我们不在user_id和friend_id表中包含谓词,这会更简单,但这可能是一个非常大(且昂贵)的行集来实现。
答案 1 :(得分:0)
试试这个:
鉴于你想要得到朋友的共同朋友1&amp; 2
select friend_id into #tbl1 from users where user_id = 1
select friend_id into #tbl2 from users where friend_id = 2
select id, name from users where id in(select friend_id from #tbl1 f1, #tbl2 f2 where f1.friend_id=f2.friend_id)