我有一个关于如何最好地组织我的数据库的概念性问题。
目前我有四个核心表users
、teachers
、students
和notifications
。但是 teachers
和 students
表都继承自 users
表,因此包含外键 user_id
。
您可能已经猜到,notifications
表是指通知。这些需要为属于员工组的所有用户显示,即受雇于另一名员工。
学生和老师都可以雇佣其他用户。
所以关键是我需要一种 Eloquent 方式来对此进行建模。代码的基本工作流程如下:
getCurrentUser->getAllEmployer(s)->getNotifications
这是我习惯的 Laravel Eloquent $user->employers()->notifications;
不幸的是,事情并没有那么简单,在这种情况下,雇主可以引用两个表格。
所以我的选择如下。
- 为
学生
和老师
建立良好的关系 作为雇主的关系。不足之处是我需要写如果 测试以检查当前用户是否属于其中一个和此代码 会经常重复。 - 添加一个
teacher_id
和student_id
到users
表。然而,每个人显然都是多余的 记录。很有可能需要添加其他列,因为 很好,因为新雇主实体的出现。 - 创建一个
employer_employee
表,其中包含两列均引用user_id
。 SQL 查询将同时加入student
和teacher
表与employer_employee
表,然后是 JOIN 使用notifications
将返回所有相关信息。然而会 与 其他选项。 - 我没有考虑过的事情。
我真的在寻找最高效、可扩展的解决方案。
感谢任何帮助。如果您能阐明为什么您的答案也是最有效的可扩展解决方案,那就太好了。
最佳答案
有个类似的问题here使用媒体父类(super class)型并添加 CD、VCR、DVD 等子类型。
这是可扩展的,因为在创建 BluRay 子类型时,您创建表以包含 BluRay 特定数据并向 MediaTypes 表添加一个条目。无需对现有数据或代码进行任何更改——当然,除了添加适用于蓝光数据的代码。
在您的情况下,用户将是父类(super class)型表,教师和学生是子类型表。
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 表类似。
由于教师和学生都可能雇用其他教师和学生,因此包含此关系的表将引用 Users 表。
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;
当然,这是一个初始草图。改进是可能的。但是对于你的编号点:
- 就业表将雇主与雇员联系起来。唯一检查是否使用户雇主不能雇用自己,否则任何用户都可以既是雇员又是雇主。
- Users 表强制每个用户是教师 ('T') 或学生 ('S')。只有定义为“T”的用户才能放在教师表中,只有定义为“S”的用户才能放在学生表中。
- Employment 表仅连接到 Users 表,而不连接到 Teachers 和 Students 表。但这是因为教师和学生既可以是雇主又可以是雇员,而不是出于任何绩效原因。通常,在初始设计期间不必担心性能。此时您主要关心的是数据完整性。关系数据库非常适合连接。 如果出现性能问题,请修复它。不要为了解决尚未存在或可能永远不会存在的问题而重组数据。
- 好吧,试一试,看看效果如何。
关于mysql - 围绕继承结构设计关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32574929/