为社交网站设计朋友表
Posted
技术标签:
【中文标题】为社交网站设计朋友表【英文标题】:Design a friends table for a social networking site 【发布时间】:2016-05-03 07:49:29 【问题描述】:您好,我遇到了关于存储用户所有好友列表的表结构的问题。在下表中,如果用户 84 请求与用户 70 和 74 建立友谊,那么用户 84 > 朋友是 70 和 74,反之亦然。类似用户 77 和 84。
但问题是,如果我想找出用户 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 设为静态,可以根据要求将其设为动态。
【讨论】:
以上是关于为社交网站设计朋友表的主要内容,如果未能解决你的问题,请参考以下文章