为社交网站设计朋友表

Posted

技术标签:

【中文标题】为社交网站设计朋友表【英文标题】:Design a friends table for a social networking site 【发布时间】:2016-05-03 07:49:29 【问题描述】:

您好,我遇到了关于存储用户所有好友列表的表结构的问题。在下表中,如果用户 84 请求与用户 7074 建立友谊,那么用户 84 > 朋友是 70 和 74,反之亦然。类似用户 7784

但问题是,如果我想找出用户 84 即用户 (70,74,77) 的所有朋友及其详细信息。 p>

我是否应该像图 2 一样输入重复记录 例如:如果用户 84 向用户 70 发送好友请求,而用户 70 接受该请求,则将插入另一行,例如 user_id 70 &friend_id 84

或者是否有任何 mysql 查询可以根据朋友表的列值加入用户表。就像如果 user_id 是 84 它将基于 friend_id 加入,如果 friend_id 是 84 那么它将通过使用 加入用户表>user_id 列。

【问题讨论】:

您可以轻松地执行 JOIN 或 UNION 以获取特定 user_id 或friend_id 的所有记录,因此您无需添加副本。 【参考方案1】:

我假设在您的系统中友谊是对称的,即如果 A 与 B 是朋友,则意味着 B 也是 A 的朋友。在这种情况下,我建议您更改 Friend 表的列以反映两者的事实人们在关系中具有平等的地位,例如

朋友

@User1_Id @User2_Id

有了这个,你就可以做这样的查询

SELECT * FROM User WHERE User.UserId IN (
    (SELECT User1_Id FROM Friend WHERE User2_Id = MY_USER_ID)
    UNION
    (SELECT User2_Id FROM Friend WHERE User1_Id = MY_USER_ID)
)

这使用子选择而不是联接,加上联合来获取朋友的用户 ID 的单个列表,具体取决于用户在 Friend 表中列出的方式。 sub-query 和 union 的文档。

可能值得保持这样,而不是通过在您的 Friends 表中为每个关系((A,B)和(B,A)保留 2 行来简化代码。如果您有 N 个用户,则 Friends 表将有多达 N*(N-1) 行,如果您复制,则一半,否则。

【讨论】:

嗨@Bob Salmon,我觉得你的答案是 100% 正确的,但你能区分 mitkosoft 给出的答案,它也可以正常工作。 @mitkosoft 的回答也不错。有 3 个不同之处:1. mitkosoft 使用当前架构,而我的架构基于一个小的架构更改,2. mitkosoft 的答案基本上是我答案的内部部分(IN 子句中的位),3. UNION 有不同修饰符 - 在我的默认为 DISTINCT,但 mitkosoft 的答案是 ALL。就返回的结果而言,在您的情况下,我认为这并不重要,因为我认为不会有任何重复。我希望 ALL 会运行得更快,因为它不进行任何重复检查,但担心重复是一个好习惯。 感谢@Bob Salmon 的宝贵回答。【参考方案2】:

我的建议不是这样做,而是使用下面的结构来处理这个问题。创建两个不同的表。 即 1- 友谊 2- 友谊状态

1-

2-

在友谊表中,当 userId1 向 userId2 发送好友请求时,recoed 被插入,状态为 1。当 userId2 接受好友请求时,状态变为 2。如果 userid2 取消请求,则状态变为 3。 即使你想获取数据。假设你想找到用户 id 为 3 的朋友。然后使用这样的查询-

SELECT userId1, userId2 from friendship where userId2=3 OR userId1 =3 AND status =2

无需重复输入。

【讨论】:

嗨@Santosh,问题不在于找到朋友ID,但我想通过使用join来获取朋友数据。假设我想找到用户 3 的所有朋友及其上表第 1、2、3 行的详细信息,它应该显示基于 userid2 的用户记录,而对于 4 和 5,它将基于 userid1。 @pkk- 是的,确保您可以通过使用关节或查询查询来找到朋友数据。几天前我尝试过相同的社交网站项目,我面临数据库问题表格结构随着我移动到个人资料、个人资料视图(自己的、朋友和公开的)、共享图片、喜欢等模块变得复杂。所以我提出了这个简单的表结构。这对我真的很有帮助。【参考方案3】:

您可以使用连接查询来获取结果。无需添加重复条目

【讨论】:

嗨,我们不能在这里直接使用 join,因为我们将与 users 表连接的列是动态的,即有时是 user_id,有时是friends_id。 @pkk 我们可以使用。我已经使用过这样的查询。所以只有我建议这个。你的评论有什么证据吗? 嗨@sujivasagam 实际上我只想根据列值获取用户数据(使用连接)。例如,如果 user_id = 84 则使用friend_id 加入,反之亦然。请您为此编写查询。【参考方案4】:

基于第一个表设计,您可以使用 UNION 来获取特定用户 ID 的所有朋友:

SELECT f.friend_id FROM friends f WHERE f.user_id = 84
UNION ALL
SELECT f.user_id FROM friends f WHERE f.friend_id = 84

输出是:

+-----------+
| friend_id |
+-----------+
|        70 |
|        74 |
|        77 |
+-----------+
3 rows in set

【讨论】:

嗨@mitkosoft 你查询工作100% 没问题。这是修改后的查询 SELECT friends.friend_id ASfriend_id,users.* FROM friends LEFT JOIN users ON(friends.friend_id=users.id) WHERE friends.user_id = 84 UNION ALL SELECT friends.user_id ASfriend_id,users。 * FROM Friends LEFT JOIN users ON(friends.user_id=users.id) WHERE friends.friend_id = 84 。我们可以在这里使用 order by 子句对数据进行排序吗? 我们也可以使用limit来获取要获取的记录吗? 是的,您可以通过两种方式 - 在每个查询中添加限制或对整个 UNION 结果集进行父 SELECT。【参考方案5】:

此查询将为您提供包括用户 XXXX 的朋友在内的所有条目

select * from friendshipTable where user_id = XXXX or friend_id = XXXX

【讨论】:

是的,你是对的,但我也想使用 join 来获取好友记录。【参考方案6】:
SELECT * FROM friends AS f 
LEFT JOIN users AS u ON f.user_id = u.user_id 
     AND f.friend_id = u.user_id 
WHERE f.friend_id = 84 OR f.user_id = 84

我没有尝试过,但希望对你有用。

【讨论】:

【参考方案7】:

经过长时间的搜索,我找到了解决问题的最佳方法,方法是使用如下连接操作,并且无需输入重复条目。 这是我的查询

SELECT  users.*  FROM friends  
  LEFT JOIN users  ON  
    (users.`id` = friends.`user_id` OR  users.`id` = friends.`friend_id`) 
        AND  
    users.`id` != '84'   
WHERE     
    friends.`user_id` = '84'   
        OR  
    friends.`friend_id`='84'

我已将 user_id=84 设为静态,可以根据要求将其设为动态。

【讨论】:

以上是关于为社交网站设计朋友表的主要内容,如果未能解决你的问题,请参考以下文章

社交网站如何计算好友更新?

社交网络数据库设计 - 朋友/块关系

我可以为我的社交网站中的每个用户创建每个表吗?

社交网络好友列表、朋友圈、帖子分享的数据库设计[关闭]

为社交网站创建提要

创建一个新的社交网站。推荐的启动框架?