mysql - 社交网络 - 推荐的 friend

标签 mysql sql

我有两个简单的 MySQL 表:用户和关系。

关系表:

user_id int(10) unsigned    NO  PRI     
friend_id   int(10) unsigned    NO  PRI 

(部分)用户表:

id  int(10) unsigned    NO  PRI     
username    varchar(128)    NO

我使用此查询选择 friend 的 friend :

SELECT f2.friend_id, u.username
FROM relations f1
JOIN relations f2 ON f1.friend_id=f2.user_id
LEFT JOIN user u ON u.id = f2.friend_id
WHERE f2.friend_id NOT IN (select friend_id from relations where user_id=@user_id) AND f1.user_id= 2 AND f2.friend_id!= 2

但我还需要得到建议的 friend ...(组中认识 2 个或更多直接 friend 的人),我对此有疑问。什么是获得推荐 friend 的好方法(查询,或者我应该用 PHP 来做?)?

最佳答案

考虑以下……这个例子假设互惠是通过为每个友谊插入两行来建立的。但是,为简单起见,以下示例不会检查友谊是否是相互的!

 DROP TABLE IF EXISTS friends;

 CREATE TABLE friends
 (initiator VARCHAR(12) NOT NULL
 ,reciprocator VARCHAR(12) NOT NULL
 ,PRIMARY KEY (initiator,reciprocator)
 );

 INSERT INTO friends VALUES 
 ('Adam','Ed'),
 ('Ed','Adam'),
 ('Adam','Ben'),
 ('Ben','Adam'),
 ('Adam','Charlie'),
 ('Charlie','Adam'),
 ('Adam','Dan'),
 ('Dan','Adam'),
 ('Ed','Ben'),
 ('Ben','Ed'),
 ('Ben','Charlie'),
 ('Charlie','Ben'),
 ('Charlie','Dan'),
 ('Dan','Charlie'),
 ('Dan','Fred'),
      ('Fred','Dan'),
 ('Adam','Fred'),
      ('Fred','Adam');

要获得 Ben 所有“ friend 的 friend ”的列表,我们可以这样做...

 SELECT y.reciprocator
   FROM friends x
   JOIN friends y
     ON y.initiator = x.reciprocator
    AND y.reciprocator <> x.initiator
   LEFT
   JOIN friends z
     ON z.reciprocator = y.reciprocator 
    AND z.initiator = x.initiator
  WHERE x.initiator = 'Ben'
    AND z.initiator IS NULL;
 +--------------+
 | reciprocator |
 +--------------+
 | Dan          |
 | Fred         |
 | Dan          |
 +--------------+

如您所见,因为 Dan 与 Adam 和 Charlie(都是 Ben 的 friend )都是 friend ,所以他的名字出现了两次。

因此,要获得 DISTINCT friend 的 friend 列表,只需包含 DISTINCT 运算符即可。

同样,要获得对 Ben 陌生但至少是 Ben 的两个 friend 的 friend 的列表,我们可以这样做...

SELECT y.reciprocator
  FROM friends x
  LEFT
  JOIN friends y
    ON y.initiator = x.reciprocator
   AND y.reciprocator <> x.initiator
  LEFT
  JOIN friends z
    ON z.reciprocator = y.reciprocator
   AND z.initiator = x.initiator
 WHERE x.initiator = 'Ben'
   AND z.initiator IS NULL
 GROUP
    BY y.reciprocator
HAVING COUNT(*) >= 2;
 +--------------+
 | reciprocator |
 +--------------+
 | Dan          |
 +--------------+

处理这个问题的互惠方面可能有几种方法,就像处理互惠本身有几种方法一样。

一种方法是用一个简单的子查询替换上面每次出现的 friends 表,例如

SELECT y.reciprocator
  FROM (SELECT a.* FROM friends a JOIN friends b ON b.reciprocator = a.initiator AND b.initiator = a.reciprocator) x

  LEFT
  JOIN (SELECT a.* FROM friends a JOIN friends b ON b.reciprocator = a.initiator AND b.initiator = a.reciprocator) y
    ON y.initiator = x.reciprocator
   AND y.reciprocator <> x.initiator

  LEFT
  JOIN (SELECT a.* FROM friends a JOIN friends b ON b.reciprocator = a.initiator AND b.initiator = a.reciprocator) z
    ON z.reciprocator = y.reciprocator
   AND z.initiator = x.initiator

 WHERE x.initiator = 'Ben'
   AND z.initiator IS NULL
 GROUP
    BY y.reciprocator
HAVING COUNT(*) >= 2; 

关于mysql - 社交网络 - 推荐的 friend ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20187230/

相关文章:

mysql - 让 SQL 像 DDL 语句一样

Mysql UNION 与动态查询

mysql - SQL 左连接与 SUM

mysql - 在 MySQL 中检测到 'x' 时添加到一个值

SQL 报告服务,参数值更新未显示

mysql - 将 Join/Subselect 查询与 SUM MYSQL 查询相结合

sql - SQL 查询中的 distinct 问题

php - 按 A-Z 顺序将名称从 sql 排序到类别

mysql - 操作数应包含 1 列???确实如此,但仍然出错。这是一个错误吗?

sql - 如何使用 SQL 命令文件创建 SQLite3 数据库文件?