我想创建一个表格,我的用户可以将彼此之间的友谊关联起来。与此同时,这个表将与我试图处理的各种其他表之间的一对多关系一起工作。
现在我正在考虑这样的事情
member_id,friend_id,有效,日期
member_id将是进行调用的用户的列,friend_id将是他们尝试绑定的朋友的列,active是切换的排序0 = pending,1 = active,date只是一个记录该特定行上最后一个活动的日期。
现在我的困惑在于,如果我要查询,我通常会查询member_id,然后根据相关的friend_id来查询剩余的查询,以便相应地向正确的人显示数据。因此,考虑到这种逻辑,这使我认为每个请求必须有2行。其中请求的member_id和请求的friend_id插入表中,然后是相反的,所以我每次都可以相应地进行查询。所以在本质上它就像对于这个特定的表所请求的每一个动作的双重浸入一样,我需要做出2个像它一样的动作来使它工作。 就优化而言,这对我来说根本没有意义。所以在我的所有问题中,处理这类关系数据的正确方法是什么?或者我真的在想这是一种处理它的方法吗?
答案 0 :(得分:6)
如果友情总是相互关联,那么您可以选择数据冗余(即两个方向都有一行)以便进行更简单的查询,或者学会使用稍微复杂的查询。除非有令人信服的理由,否则我个人会避免数据冗余 - 你不仅浪费空间和性能,而且在执行它时你需要小心 - 一个简单的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
)
)
顺便说一句,在这个方案中,您可能希望将member_id
和friend_id
重命名为friend1_id
和friend2_id
......
答案 1 :(得分:5)
两种观察方式:
WHERE ((friend_id = x AND member_id = y) OR (friend_id = y AND member_id = x))
允许您通过简单地说明关系的一方来进行查询。如果添加了双方,则此方法仍然可以工作,而不会导致返回重复的行。
相反,添加关系的两面,以便您的查询包含
WHERE friend_id = x AND member_id = y
不仅使查询更容易编写,而且更容易规划(意味着更好的数据库性能)。
我的投票是针对后一种选择。
答案 2 :(得分:1)
漂亮 - 你的桌子没问题。
ALSO: 我不确定这个基数是“一对多”,还是“多对多”:
http://en.wikipedia.org/wiki/Cardinality_%28data_modeling%29
答:坦率地说,我没有看到查询“会员对朋友”或“朋友对会员”(或任何其他组合 - 例如分享朋友的朋友)的任何问题。再次,它看起来不错。问:我要查询我通常会查询member_id然后根据 查询的其余部分关闭相关的friend_id以显示数据 相应的人才
答案 3 :(得分:0)
介绍一个帮助表,如:
users
user_id, name, ...
friendship
user_id, friend_id, ....
select u.name as user, u2.name as friend from users u
inner join friendship f on f.user_id = u.user_id
inner join users u2 on u2.user_id = f.friend_id
我认为这与您所拥有的完全相似,只是以查询为例。