围绕继承结构设计关系

时间:2015-09-14 22:30:26

标签: mysql laravel database-design relational-database

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

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

您可能已经猜到的notifications表引用了通知。这些需要出现在属于雇员组的所有用户中,即在另一个用户的雇佣下。

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

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

getCurrentUser->getAllEmployer(s)->getNotifications

这是Laravel Eloquent我曾经$user->employers()->notifications;

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

所以我的选择如下。

  1. studentteacher创建雄辩的关系 作为雇主的关系。缺点是我需要写,如果 测试以检查当前用户是否属于该代码 会经常重复。
  2. 添加teacher_idstudent_id users表。然而,每个人显然都是多余的 记录。需要添加其他列的可能性很大 很好,因为新雇主实体的出现。
  3. 创建一个employer_employee表,其中包含两个引用user_id的列。 SQL查询将LEFT JOIN student和。{ 带有teacher表的employer_employee表,然后是JOIN notifications将返回所有相关内容。不过会 与此相比,如此多的连接会降低查询的速度 其他选择。
  4. 我没有考虑过的事情。
  5. 我真的在寻找最有效,可扩展的解决方案。

    感谢任何帮助。如果你能澄清为什么你的答案是最有效的可扩展解决方案,那将是一流的。

1 个答案:

答案 0 :(得分:1)

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

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

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

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 )
);

学生表的构成与教师表类似。

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

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. “就业”表仅连接到“用户”表,而不是“教师”和“学生”表。但这是因为教师和学生都可以是雇主和雇员,而不是出于任何表现原因。通常,在初始设计期间不要担心性能。此时您主要关心的是数据完整性。关系数据库非常适合连接。 如果出现性能问题,请修复它。不要重构数据以解决尚不存在且可能永远不存在的问题。
  4. 好吧,试一试,看看它是如何运作的。