1

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

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

PK - (User1, User2)

在请求字段中,当用户 1 向用户 2 提出请求时存储“0”,当用户 2 批准请求时存储“1”。

当我想检索用户的所有朋友时,就会出现问题。我每次都必须检查请求字段是“0”还是“1”。还有其他方法吗?如果我有另一个存储 Friend 请求的所有详细信息的表会更好吗?

4

2 回答 2

2

在评论中,您基本上声明已建立的友谊(而不是请求)在您的设置中始终是对称的。在这种情况下,您基本上有两个选择:您可以将其存储在两行中,或者通过匹配任一列来选择它。前者将产生更简单的查询,但后者将确保对称性是数据库结构中固有的,并且还将避免存储重复数据。所以我会选择后者,即某种形式的WHERE (User1 = XX or User2 = XX ). 查询所花费的时间可能是仅查询一列所占用的相同行数的两倍,但由于行数仅为其他存储方案的一半,因此在性能方面的净影响应该可以忽略不计.

您是否需要单独的请求表或已建立的友谊取决于这两者的相似程度,无论是在关联数据方面还是在应用程序中的控制流方面。因此,例如,如果您想向用户显示一个列表,该列表同时显示他已建立的友谊和他的未决请求,可能有不同的颜色或其他,但在同一个列表中,那么在数据库中拥有一个表会更多适当。另一方面,如果您主要将请求和友谊分开处理,那么拥有两张桌子会更自然。而且,如果在某个时候,您决定友谊需要类似的属性,share_calendar而请求需要类似confirmation_key或其他的属性,那么使用不同的表会更好。

如果您决定将其设为单个表,我建议为枚举提供更多描述性值,例如调用列status和值requestedestablished. 例如,我乍一看会将值解释request = 1为“这只是一个请求,而不是既定的友谊”,这与您所联想的含义完全相反。当不同的人需要维护代码时,这种模糊性可能会导致错误。几年后,你将成为一个与现在不同的人,甚至你自己也可能会误解你的旧代码。所以要在那里描述。

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

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'

This will restrict the data to established friendships only, and will take care of symmetrizing things for you. Using such views in your queries, you can avoid having to deal with all the details of the table structure in every query. And if you ever change those details, there will be less places to change.

于 2012-08-13T20:28:02.717 回答
1

我会将您的数据分解为requestsand friendships。当 arequest被批准后,将其转换为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 = ? 
于 2012-08-13T17:50:04.273 回答