MySQL查询共同的朋友

ilh*_*han 10 mysql sql mutual-friendship

可能重复:
MYSQL选择共同的朋友

我有一张友谊的桌子,友谊只存储在一条线上.所以没有重复的条目.

id  Person1    Person2  status
1         1          2  friend
2         1          3  friend
3         2          3  friend
4         3          4  friend
Run Code Online (Sandbox Code Playgroud)

什么MySQL查询(加入,内部联接)将帮助我找到人#1和人#3之间的共同(共同)朋友?此示例中的输入为{1,3},输出应为{2},因为Person#2是bot#1和#3的朋友.

TMS*_*TMS 9

好吧,到目前为止唯一可能工作的查询是Simon的......但这真是一种过度杀伤 - 如此复杂的讨厌查询(2个子查询与2个联盟!)这么简单,你需要放置一笔赏金吗?:-)如果你有1000多个用户,那么查询会很慢,因为地狱 - 记忆,它是二次的,并且由于子查询中的联合,几乎不会使用任何索引!

我建议再次重新考虑设计并允许2个重复的行为友谊:

id  Person1    Person2  status
1         1          2  friend
2         2          1  friend
3         1          3  friend
4         3          1  friend
Run Code Online (Sandbox Code Playgroud)

您可能认为效率低下,但简化后将允许将查询重写为简单连接:

select f1.Person2 as common_friend
from friends as f1 join friends as f2
    using (Person2)
where f1.Person1 = '$id1' and f2.Person1 = '$id2' 
    and f1.status = 'friend' and f2.status = 'friend'
Run Code Online (Sandbox Code Playgroud)

哪个会快!(不要忘记为Person1,2添加索引.)我已经建议在其他非常讨厌的数据结构中进行类似的简化(重写子查询到连接),它已经加快了查询从永恒到闪电般的瞬间!

所以看起来可能是一个很大的开销(一个友谊的2行)实际上是一个很大的优化:-)

此外,它将使"查找X的所有朋友"等查询变得更加容易.并且不需要花更多的奖金:-)

  • 你是对的 - 我一直在想@George的当前架构没有数据异常,尽管很难查询.然后我意识到,在当前的模式中,没有什么能阻止现有关系的反转被创建并导致令人困惑的删除.我现在看到当前和你提出的架构都处于大致相同的规范化水平. (2认同)

Sta*_*arx 0

我认为这很简单地通过这个实现

SELECT * FROM friends

WHERE
     (Person1 = '1' or Person2 = '1') && 
     (Person1 = '2' or Person2 = '2') &&
     status = 'friend'
Run Code Online (Sandbox Code Playgroud)

鉴于您正在尝试找到人 1 和人 2 之间的相互关系