【问题标题】:Designing relationships around an inheritance structure围绕继承结构设计关系
【发布时间】:2015-09-16 08:33:25
【问题描述】:

我有一个关于如何最好地组织我的数据库的概念性问题。

目前我有四个核心表usersteachersstudentsnotifications。但是teachersstudents 表都继承自users 表,因此包含外键user_id

您可能已经猜到了notifications 表指的是通知。这些需要为属于员工组的所有用户显示,即受雇于另一个人。

学生和教师都可以雇用其他用户。

所以关键是我需要一种雄辩的方式来对此进行建模。代码的基本工作流程如下:

getCurrentUser->getAllEmployer(s)->getNotifications

这是我习惯的 Laravel Eloquent $user->employers()->notifications;

不幸的是,这并不像在这种情况下雇主可以参考两张表那么简单。

所以我的选择如下。

  1. studentteacher 创建 Eloquent 关系 作为雇主的关系。不足之处是我需要写如果 测试以检查当前用户是否属于任何一个以及此代码 会经常重复。
  2. teacher_idstudent_id 添加到 users 表。然而,一个显然是多余的 记录。需要添加其他列的机会很可能是 这要归功于新雇主实体的出现。
  3. 创建一个employer_employee 表,其中包含两列都引用user_id。 SQL 查询将 LEFT JOIN 两个 studentteacher 表与 employer_employee 表,然后是 JOIN notifications 将返回所有相关的。然而会 与 其他选项。
  4. 我没有考虑过的事情。

我真的在寻找最有效、可扩展的解决方案。

感谢任何帮助。如果您能阐明为什么您的答案也是最有效的可扩展解决方案,那就太好了。

【问题讨论】:

    标签: mysql laravel database-design relational-database


    【解决方案1】:

    有一个类似的问题here 使用 Media 超类型并添加 CD、VCR、DVD 等的子类型。

    这是可扩展的,例如在创建 BluRay 子类型时,您可以创建表以包含特定于 BluRay 的数据,并向 MediaTypes 表添加一个条目。现有数据或代码无需更改——当然,除了添加可用于蓝光数据的代码。

    在您的情况下,用户将是超类型表,教师和学生是子类型表。

    create table Users(
        ID      int not null auto_generating,
        Type    char( 1 ) check( Type in( 'T', 'S' )),
        -- other data common to all users,
        constraint PK_Users primary key( ID ),
        constraint UQ_UserType unique( ID, Type ),
        constraint FK_UserTypes foreign key( Type )
            references UserTypes( ID )
    );
    create table Teachers(
        TeacherID int not null,
        TeacherType char( 1 ) check( TeacherType = 'T' )),
        -- other data common to all teachers...,
        constraint PK_Teachers primary key( TeacherID ),
        constraint FK_TeacherUser foreign key( TeacherID, TeacherType )
            references Users( ID, Types )
    );
    

    Students 表的构成类似于 Teachers 表。

    由于教师和学生都可以雇用其他教师和学生,因此包含这种关系的表将引用用户表。

    create table Employment(
        EmployerID    int not null,
        EmployeeID    int not null,
        -- other data concerning the employment...,
        constraint CK_EmploymentDupes check( EmployerID <> EmployeeID ),
        constraint PK_Employment primary key( EmployerID, EmployeeID ),
        constraint FK_EmploymentEmployer foreign key( EmployerID )
            references Users( ID ),
        constraint FK_EmploymentEmployee foreign key( EmployeeID )
            references Users( ID )
    );
    

    据我了解,通知按雇主分组:

    create table Notifications(
        EmployerID    int not null
        NotificationDate date,
        NotificationData varchar( 500 ),
        -- other notification data...,
        constraint FK_NotificationsEmployer foreign key( EmployerID )
            references Users( ID )
    );
    

    查询应该足够简单。例如,如果用户想查看其雇主的所有通知:

    select  e.EmployerID, n.NotificationDate, n.NotificationData
    from    Employment  e
    join    Notifications n
        on  n.EmployerID = e.EmployerID
    where   e.EmployeeID = :UserID;
    

    当然,这是最初的草图。细化是可能的。但是对于您的编号:

    1. 就业表将雇主与雇员联系起来。唯一的检查是否使用户雇主不能雇用自己,否则任何用户都可以是雇员和雇主。
    2. Users 表强制每个用户是教师 ('T') 或学生 ('S')。只有定义为“T”的用户可以放置在教师表中,只有定义为“S”的用户可以放置在学生表中。
    3. Employment 表仅连接到 Users 表,而不连接到 Teachers 和 Students 表。但这是因为教师和学生都可以是雇主和雇员,而不是出于任何绩效原因。一般来说,在初始设计期间不要担心性能。此时您最关心的是数据完整性。关系数据库非常适合连接。 如果出现性能问题,请修复它。不要重组您的数据来解决尚不存在且可能永远不会存在的问题。
    4. 好吧,试试这个,看看它是如何工作的。

    【讨论】:

      猜你喜欢
      • 2011-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多