chr*_*ris 2 mysql database database-design one-to-many
我想创建一个表格,我的用户可以将彼此之间的友谊关联起来.同时这个表将与我试图处理的各种其他表之间的一对多关系一起工作.
现在我在考虑这样的事情
member_id,friend_id,活跃,日期
member_id将是进行调用的用户的列,friend_id将是他们尝试绑定的朋友的列,active是切换的排序0 = pending,1 = active,date只是记录的日期该特定行的最后一个活动.
现在我的困惑在于,如果我要查询,我通常会查询member_id,然后根据相关的friend_id来查询剩余的查询,以便相应地向正确的人显示数据.因此,考虑到这种逻辑,这使我认为每个请求必须有2行.其中请求的member_id和请求的friend_id插入表中,然后是相反的,所以我每次都可以相应地进行查询.所以在本质上它就像对于这个特定的表所请求的每一个动作的双重浸入一样,我需要做出2个像它一样的动作来使它工作.就优化而言,这对我来说根本没有意义.所以在我的所有问题中,处理这类关系数据的正确方法是什么?或者我真的在想这是一种处理它的方法吗?
如果友谊始终是相互的,那么您可以在数据冗余(即两个方向都有一行)之间进行选择,以便进行更简单的查询,或者学会使用稍微复杂的查询.除非有令人信服的理由,否则我个人会避免数据冗余 - 你不仅浪费空间和性能,而且在执行它时你需要小心 - 一个简单的CHECK无法引用其他行并且取决于你的DBMS触发器可以限制它对变异表的作用.
确保每个友谊只有一行的简单方法是始终在较低值member_id
和较高值中插入friend_id
(制定约束CHECK (member_id < friend_id)
以强制执行).然后,当您查询时,您将在两个方向上进行搜索 - 例如,查找给定人员的所有朋友(标识为person_id
)将如下所示:
SELECT *
FROM
person
WHERE
id <> :person_id
AND (
id IN (
SELECT friend_id
FROM friendship
WHERE member_id = :person_id
)
OR
id IN (
SELECT member_id
FROM friendship
WHERE friend_id = :person_id
)
)
Run Code Online (Sandbox Code Playgroud)
顺便说一句,在这个方案中,你可能要重命名member_id
和friend_id
,比方说,friend1_id
和friend2_id
...
两种方式来看待它:
WHERE ((friend_id = x AND member_id = y) OR (friend_id = y AND member_id = x))
Run Code Online (Sandbox Code Playgroud)
将允许您通过简单地说明关系的一方来进行查询.如果添加了双方,则此方法仍然可以工作,而不会导致返回重复的行.
相反,添加关系的两边,以便您的查询包含
WHERE friend_id = x AND member_id = y
Run Code Online (Sandbox Code Playgroud)
不仅使查询更容易编写,而且更容易规划(意味着更好的数据库性能).
我的投票是针对后一种选择.