我知道在这个主题上有很多结果,但是它们并没有帮助我。

我有一个与user1和user2的好友表。

真正的朋友是当user1是与user2的朋友,而user2是与user1的朋友。

朋友请求是当user1与user2成为朋友时。看起来像这样:

 user1 | user2
 -------------
 1     | 2
 2     | 1
 1     | 3
 3     | 1
 1     | 5


该查询看起来如何获得#1的真正朋友?

我试过了,但返回null:

SELECT user2 FROM friends WHERE user1 = 1 AND user2 = 1


查询还将如何查找朋友请求?

最佳答案

一种实现方法是使用JOIN操作:

SELECT f.user2
  FROM friends f
  JOIN friends r
    ON r.user1 = f.user2
   AND r.user2 = f.user1
 WHERE f.user1 = 1


假定存在两个元组来标识“真实朋友”关系,即1n之间的真实朋友关系将由表中的两行表示:(1,n)(n,1)

连接条件中的谓词将返回的行限制为具有匹配的“反”元组的行。

注意:JOIN操作通常比等效的IN (subquery)EXISTS (subquery)模式执行得更好,但是对于小的集合,性能差异可以忽略不计。在更大的集合中,性能差异变得明显。

可以使用EXISTS谓词返回等效结果(通常效率较低):

SELECT f.user2
  FROM friends f
 WHERE f.user1 = 1
   AND EXISTS ( SELECT 1
                  FROM friends r
                 WHERE r.user1 = f.user2
                   AND r.user2 = f.user1
              )


或IN谓词:

SELECT f.user2
  FROM friends f
 WHERE f.user1 = 1
   AND f.user2 IN ( SELECT r.user1
                      FROM friends r
                     WHERE r.user2 = f.user1
                  )


(如果friends(user1,user2)上没有唯一的约束,那么JOIN可能会返回一些重复的行,而其他查询可能不会返回这些行,但是所有查询都不保证不会返回任何重复项。如果没有唯一的约束,并且您不希望返回任何重复项,则可以在任何这些语句的开头的SELECT之后添加DISTINCT关键字,或者在任何这些语句的末尾添加GROUP BY f.user2。

为了使结果集更具确定性(即每次运行查询都返回相同的结果),您可以添加ORDER BY子句。 (但是对于GROUP BY并不需要,因为MySQL隐式对GROUP BY表达式执行ORDER BY。)



跟进

说明如何将结果与用户表中的名称绑定?谢谢。以及如何获得“不真实”的朋友?

要从用户表中获取名称,我们只需向用户表中添加一个JOIN即可,假设id是主键列,而user1和user2列是用户表的外键...

SELECT f.user2
     , u.name
  FROM friends f
  JOIN user u
    ON u.id = f.user2
  JOIN friends r
    ON r.user1 = f.user2
   AND r.user2 = f.user1
 WHERE f.user1 = 1


“不真实”的朋友将表示为元组(表中的行)(1,n),它没有对应的逆元组(n,1)。为了找到这些行,我们使用了一个反联接模式,这是一个OUTER联接(从一侧返回所有行加上任何匹配的行),然后是一个谓词,该谓词排除找到匹配项的行(检查a中是否为NULL)。如果存在匹配项,则保证不为null的列就是我们的操作方式):

这将找到没有匹配的(1,n)的所有(n,1)元组:

SELECT f.user2
     , u.name
  FROM friends f
  JOIN user u
    ON u.id = f.user2
  LEFT
  JOIN friends r
    ON r.user1 = f.user2
   AND r.user2 = f.user1
 WHERE r.user1 IS NULL
   AND f.user1 = 1


我们必须将其翻转以得到另一面,没有匹配的(n,1)行的(1,n)行:

SELECT f.user1
  FROM friends f
  JOIN user u
    ON u.id = f.user1
  LEFT
  JOIN friends r
    ON r.user2 = f.user1
   AND r.user1 = f.user2
 WHERE r.user2 IS NULL
   AND f.user2 = 1

关于mysql - 从好友列表中找到真正的 friend ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18342752/

10-14 14:46