双向关系的数据库设计

Jos*_*hua 5 database-design

我正在使用关系表对用户之间的双向关系进行建模。每个关系涉及两个且仅两个用户。关系的每个方向都允许 3 种不同的状态(待定、阻止、允许)。

为了减少内存开销,我决定使用以下系统来保留由单行而不是每个方向一行表示的整个关系。

较小的 user_id 始终存储为 user_a,较大的 user_id 存储为 user_b,因此不存在错误风险。

我正在寻求关于是否应该用单列(3x3 个选项)或两个水平列(各有 3 个选项)来表示两个方向的反馈。

IE

... | status_a_b

A_Pending_B_Pending
A_Pending_B_Blocked
A_Pending_B_Allowed
A_Blocked_B_Pending
A_Blocked_B_Blocked
A_Blocked_B_Allowed
A_Allowed_B_Pending
A_Allowed_B_Blocked
A_Allowed_B_Allowed
Run Code Online (Sandbox Code Playgroud)

... | status_a | status_b

Pending | Pending
Blocked | Blocked
Allowed | Allowed
Run Code Online (Sandbox Code Playgroud)

谢谢你!

Bra*_*adC 1

为了减少内存开销,

这永远不应该成为数据库设计中的因素。让引擎来担心吧;只需根据您将如何使用数据来创建您的设计。

我决定使用以下系统来保持由单行而不是每个方向一行表示的整个关系。

这很好,但在这两种情况下,您都必须执行两个单独的查询(或两个条件)才能找到用户的所有相关关系:

SELECT * 
FROM RELATIONSHIPS
WHERE From_User = @UserID OR To_User = @UserID
Run Code Online (Sandbox Code Playgroud)

请注意,如果两种类型的用户之间存在有意义的差异,则情况可能会略有不同。比如说,介于VENDORSCLIENTS或某物之间。但听起来这两者是可以互换的。

我正在寻求关于是否应该用单列(3x3 个选项)或两个水平列(各有 3 个选项)来表示两个方向的反馈。

我不会将它们塞进一列中,您只需在需要使用它们时将它们解析出来,这违反了规范化第一规则

编辑:这是一个(人为的)示例来说明我的意思:

假设您正在为社交网络设计一个数据库,该数据库更像 Twitter(user_a 可以关注 user_b,无论 user_b 是否关注 user_a),而不像 Facebook(user_a 和 user_b 要么是“朋友”,要么不是)。

因此,如果 Marsha 关注 Joe,但 Joe 不关注 Marsha,我们有两种方法来创建“关注”表:

Followed     Follower    Status
---------    --------    ------
Joe          Marsha      T
Marsha       Joe         F
Run Code Online (Sandbox Code Playgroud)

或者

User1     User2    RtL_Follow_Status   LtR_Follow_Status
-----     ------   -----------------   -----------------
Joe       Marsha   T                   F              
Run Code Online (Sandbox Code Playgroud)

当然,第二个可能会为您节省一两个字节(或者不会,因为我什至可能不需要一行来表明 Joe 不关注 Marsha),但第一个更容易查询,特别是对于最可能的应用程序需求:

--Show all users following Joe
SELECT [Follower]
FROM [Follow_v1]
WHERE [Followed] = 'Joe'
AND [Status] = TRUE
Run Code Online (Sandbox Code Playgroud)

SELECT [User2] as [Follower]
FROM [Follow_v2]
WHERE [User1] = 'Joe'
AND [RtL_Follow_Status] = TRUE

UNION ALL

SELECT [User1] as [Follower]
FROM [Follow_v2]
WHERE [User2] = 'Joe'
AND [LtR_Follow_Status] = TRUE
Run Code Online (Sandbox Code Playgroud)

现在你的应用程序可能不是这样的,或者可能有原因我在拉起关系时总是需要知道反向跟随状态,但我想说的是“节省几个字节”是一个低优先级与使数据库易于理解和易于查询相比。

另请注意,第一个示例也可能表现更好,随着应用程序的增长,这可能比节省几个字节更重要。