2012-08-13 68 views
1

我一直在社交网站上工作。这里用户请求另一个用户成为他的朋友(朋友请求)。我想到了一个“朋友”表看起来像社交网站的朋友桌

Table Name: Friends 
Coloumns : 
    User1 - Int - FK 
    User2 - Int - FK 
    Request - Enum('0','1') 
    Time - DateTime 

PK - (User1, User2) 

在请求字段“0”时,请求由用户1发到用户2,当请求已获得用户2“1”被存储在存储中。

问题出现在我想要检索用户的所有朋友时。我必须每次检查请求字段是否为'0'或'1'。还有另一种方法可以做到吗?如果我有另一张存储朋友请求的所有细节的表,会更好吗?

+1

为什么这是一个问题?它不应该只要你有请求字段索引。做一个像SELECT * FROM friends WHERE User1 = XX和Request = 1'这样的查询应该没问题。 – 2012-08-13 17:49:51

+0

@MikeBrant如果User1是User2的好友,那么User2也是User1的好友。因此,查询将成为'SELECT * FROM WHERE(User1 = XX或User2 = XX)和Request = 1'。不是很复杂吗? – Vicky 2012-08-13 18:09:36

回答

1

在评论你基本上指出,建立友谊(而非请求)在您的设置总是对称。在这种情况下,您基本上有两种选择:您可以将其存储在两行中,也可以通过匹配任一列来选择它。前者将产生更简单的查询,但后者将确保对称性是数据库结构中固有的,并且也将避免存储重复数据。所以我会选择后者,即某种形式的WHERE (User1 = XX or User2 = XX)。查询可能需要两倍的时间,因为只有一列的查询在同一行数上需要,但由于行数仅为其他存储方案的一半,因此就性能而言的净效应应该可以忽略不计。

您是否希望为请求或已建立的友谊提供单独的表格取决于这两者在应用程序中的关联数据和控制流程方面的相似程度。举个例子,如果你想给用户显示一个单独的列表,这个列表显示他已建立的友谊和他的未决请求,可能用不同的颜色或其他,但是在同一个列表中,然后在数据库中有一个单独的表格会更多不合适。另一方面,如果你主要分别处理请求和友谊,那么有两张表会更自然。如果在某个时候,你认为一个freindship需要像share_calendar这样的属性,而一个请求需要像confirmation_key这样的属性,或者其他什么,那么你会更好地使用不同的表格。

如果您决定将此表制作为单个表格,我会为该枚举提供更多描述性值,例如调用列status和值requestedestablished。举个例子,我乍一看将request = 1的一个值解释为“这只是一个请求,而不是一个确定的freindship”,与你所关联的含义完全相反。当不同的人需要维护代码时,这种歧义可能导致错误。在几年之内,你将足够与现在不同,你甚至可能会误解你的旧代码。所以要在那里描述。

还有一点需要注意:您可能总是使用视图来调整数据库对查询的显示方式。例如,你可以创建一个视图

CREATE VIEW SymmetricEstablishedFriends AS 
SELECT User1 AS Me, User2 AS Friend, Time 
FROM Friends 
WHERE Status = 'established' 
UNION 
SELECT User2 AS Me, User1 AS Friend, Time 
FROM Friends 
WHERE Status = 'established' 

这将限制数据只建立友谊,并将照顾对称的东西给你。在查询中使用这些视图,可以避免在每个查询中处理表结构的所有细节。如果你改变这些细节,将会有更少的地方需要改变。

+0

Thanx。我想我得到了我的答案。 – Vicky 2012-08-13 20:39:53

1

我会打破你的数据requestsfriendships。当request被批准时,将其转换为friendship。他们确实是两个不同的对象,应该这样对待。

Requests :: 
    requesting_user_id : int() 
    requested_user_id : int() 
    date_requested  : datetime() 
    status_id   : int() 

Statuses :: 
    (Active, Declined, Accepted, Ignored) 

Friendships :: 
    friendship_id  : int() 
    user_id   : int() 
    friend_id   : int() 

也许删除请求,如果它被拒绝,或有一个列(让人们不要重复请求同一用户的友谊)。你不得不请求转换成两个友谊(每个方向一个),便于索引

SELECT friend_id FROM friendships WHERE user_id = ? 
+0

所以我应该存储两个元组,像user1,user2和user2,user1。这样对吗? – Vicky 2012-08-13 18:12:30

+0

在'友谊'?是的,这似乎是有道理的。 – 2012-08-13 18:27:08

+0

插入2行并删除2行看起来像是一个漫长的过程。 – Vicky 2012-08-13 19:15:51