两个实体之间的关系

时间:2012-01-05 13:51:15

标签: sql relationships entities

我有一个情况:

  1. 我有一个创建事件的用户(创建者)(每个事件属于一个用户)
  2. 每个活动都可以邀请其他用户(参与者)(每个用户属于一个活动)
  3. 基本上,有两个实体(用户和事件),但关系并不简单。 我的意思是,创建活动的用户可能与参加活动的人不一样。用户可能只是参与者,但不是创建者。

    情况类似于this

    我意识到这些关系不仅仅是多对多的。

    例如,我可以创建两个具有两个关系的表(循环关系)。 要打破这个圈子,我需要允许创建一个没有事件的用户(参与者),暂时为其分配NULL,或者通过创建另一个列(布尔值)来指示该用户是否也是创建者。

    但是我通过创建第三个表来解决它:

    enter image description here

    Diagram 1

    第三个表存储事件及其参与者。

    我还找到了解决这个问题的另一种方法。它涉及4个表:

    1. 用户(用户可以是创建者或参与者)

    2. 创作者(创作者是创建事件的用户)

    3. 事件(每个事件属于一个创建者)

    4. 参与者(参与者是参与活动的用户,一个活动有很多参与者)

    5. 这些关系看起来像这样:

      enter image description here

      Diagram 2

      哪种解决方案更好?

      我喜欢有两张桌子的那张,但我只需要深入挖掘并找到合适的。

3 个答案:

答案 0 :(得分:2)

我坚持使用三个表的解决方案,因为事件总是由一个用户创建。 EventMember表解决了UserEvent之间的n:m关系,是必要的。

引入第四个表Creator毫无意义,因为它只添加了一个JOIN来获取事件的创建者。

答案 1 :(得分:1)

最初声明的规则

  

创建活动的用户可能与参加活动的用户不同。用户可以   只是一个参与者,但不是创造者。

这似乎表明,对于每个事件,给定用户可能是参与者或创建者,但不是两者。

然而,在评论中,OP后来表示:

  

用户可以是参与者,创建者或两者兼而有之。

以下代码基于先前的假设(正如我在评论中明确指出的那样);适应后来澄清的唯一调整是放弃CHECK约束:

-- Rule: for each event, a given user may be an attendee or a creator but not both.
-- Rule: each event has zero or one creator.
-- Rule: each event has zero, one or many attendees.
-- General Rule: a table models an entity or a relationship but never both.

CREATE TABLE Users 
(
 user_name VARCHAR(20) NOT NULL, 
 UNIQUE (user_name)
);

CREATE TABLE Events 
(
 event_name VARCHAR(30) NOT NULL, 
 UNIQUE (event_name)
);

CREATE TABLE EventCreators 
(
 event_name VARCHAR(30) NOT NULL,
 creator_user_name VARCHAR(20) NOT NULL, 
 UNIQUE (event_name),  
 UNIQUE (event_name, creator_user_name),
 FOREIGN KEY (event_name) 
    REFERENCES Events (event_name), 
 FOREIGN KEY (creator_user_name) 
    REFERENCES Users (user_name)    
);

CREATE TABLE EventAttendees
(
 event_name VARCHAR(30) NOT NULL,
 creator_user_name VARCHAR(20) NOT NULL,
 attendee_user_name VARCHAR(20) NOT NULL,
 UNIQUE (event_name, attendee_user_name),  
 FOREIGN KEY (event_name, creator_user_name) 
    REFERENCES EventCreators (event_name, creator_user_name), 
 FOREIGN KEY (attendee_user_name) 
    REFERENCES Users (user_name), 
 CHECK (creator_user_name <> attendee_user_name)
);

答案 2 :(得分:0)

我这样做:

3张桌子(比如多对多)

  

表1:用户

     

表2:Users_Events

     

表3:事件

表2将包含: - 表1中的FK

  • 表3中的FK

  • 属性是关系的性质(组织者或与会者)......这可以转换为关系表,然后表2将包含该表的FK

  • 发起关系的日期(在某些时候你肯定需要这个:))

因此,如果我们说Bob今天创建一个活动,并且明天将Sarah和John添加为与会者,那么您将拥有(第一列是表1和2的PK):

  

表1 1 - Bob 2 - Sarah 3 - John

     

表2 1 - A - 组织者 - 05.01.2012 2 - A - 参加者 - 06.01.2012 3    - A - 参加者 - 2012年6月6日

     

表3 A - 超级新事件

如果您希望Bob参加会议,则必须在表2中创建新记录 1 - A - 参加者 - 2012年6月6日

然后,如果您需要参加活动A,则需要加入表1 2和3并在table_2上过滤“参加者”

为了避免在组织者参加的情况下进行双重输入,您可以通过这种方式获得表2:

表2将包含: - 表1中的FK - 表3中的FK - 参加者(布尔) - 组织者(布尔)

这更加灵活,例如,如果您以后需要跟踪谁将在会议中发表演讲,您可以在不破坏表格的情况下引入新的列播放器。如果您预见到许多角色,那么这将无法扩展