目前,我对我的表和关系进行了此设置:
情况:
有些员工参加课程。他们在名单上签名,这是该课程独有的。这些课程可以由不同的教师多次教授。每门课程可能有不同学生的多个名册(不同课程的不同名册)。还有其他规格,但在大多数情况下,员工/教师表是我关心的。
我的问题是,可能存在教师也是雇员的情况。两个表之间的唯一区别是使用InstructorID而不是EmployeeID。这会为我的数据创建一些冗余。我想避免这种情况,并尝试根据最佳实践来构建它。有没有办法将两个表中的数据组合在一起,以便在任何时候,我可以查询所有教授某些员工课程的教师的表格?
我想到了在Employees表中添加Yes / No的“isInstructor”字段。然后,我可以检查一个人是否有。但是,我觉得这是一个可怕的想法。有人建议在employeeID中添加一个前缀,以指定他们是一名教师。还有人建议,也许我会添加一个额外的字段,其中包含也是员工的教师的标识符。
基本上,我想知道这个问题的最佳实践方法是什么。我应该将数据分开并分成两个表格,还是应该将它们组合起来并添加内容?对结构的其余部分的任何建议也受到赞赏。这是我在这里的第一个问题,所以如果需要更多细节,请告诉我。
答案 0 :(得分:0)
我会从Instructors
{删除Department
移除Instructors->DeptID
并将EmployeeID
作为外键放入Instructors
。所以没有EmployeeID的教师(实际上是null
ID)是外部教练。
这仍然会使Instructors
处于非规范化状态,但应该足以满足您的目的。
答案 1 :(得分:0)
教师和员工都是人。 (我故意使用varchar(5),所以你不能在生产中使用它,至少出现来考虑名字。)
create table people (
p_id integer primary key,
first_name varchar(5) not null,
last_name varchar(5) not null,
dept_id integer not null references departments
);
insert into people values
(1, 'Robin', 'Mings', 1),
(2, 'Ora', 'Black', 1),
(3, 'Sheri', 'Johns', 2),
(4, 'Dex', 'Sims', 3);
最佳实践:如果要对表名使用复数,则始终使用复数。如果您想使用单面信息表格,请始终使用单面。 (我使用复数。)
使用表格捕获有关某人是否受雇以及某人是否为教师的详细信息。至少你需要知道的是他们的身份证号码。 Robin Mings和Sheri Johns是教练。
create table instructors (
p_id integer primary key references people
);
insert into instructors values
(1), (3);
教练Sheri Johns不是雇员。但其他人都是。
create table employees (
p_id integer primary key references people
);
insert into employees values
(1), (2), (4);
在“雇员”和“教师”表中,使用“p_id”(“人员”中的列名称)或“emp_id”等列名称的选择取决于应用程序。
这些课程可以由不同的教师多次教授。
不,他们不能。您的设计每个课程只允许一个日期。区分课程和课程。课程是在特定教师的指导下开设的课程,它从特定的日期开始。
create table courses (
course_id integer primary key,
course_name varchar(5) not null unique,
course_desc varchar(5) not null, -- unique?
course_objectives varchar(5) not null -- Think about whether this deserves its own table.
);
insert into courses values
(1, 'AP101', 'Desc', 'Obj'),
(2, 'AR101', 'Desc', 'Obj');
最佳实践:请勿在表名中使用 list 等字词。没有人说,“你应该参加这个课吗?让我查看我的名单。”此外,语义计数。如果您使用“roster_list”和“course_list”(在您的情况下实际上不是课程或名单的列表),为什么不使用“employee_list”,“department_list”等? List 只是噪音。选择更好的词语。
create table classes (
course_id integer not null references courses,
instructor_id integer not null references instructors (p_id),
start_date date not null,
-- I have no idea what completion_time means, so I omitted it.
primary key (course_id, instructor_id, start_date)
);
insert into classes values
(1, 1, '2015-04-01'),
(2, 3, '2015-04-15');
根据我的经验,员工报名参加课程,而不是课程。 (您使用了 sessions 这个词,但在您的设计中没有使用它。)根据应用程序的不同,您可能需要比此更多的表。
create table class_rosters (
course_id integer not null,
instructor_id integer not null,
start_date date not null,
employee_id integer not null references employees (p_id)
on update restrict on delete cascade,
primary key (course_id, instructor_id, start_date, employee_id),
foreign key (course_id, instructor_id, start_date)
references classes (course_id, instructor_id, start_date)
on update cascade on delete cascade
);
insert into class_rosters values
(1, 1, '2015-04-01', 2),
(1, 1, '2015-04-01', 4),
(2, 3, '2015-04-15', 1), -- An instructor is taking this class.
(2, 3, '2015-04-15', 2),
(2, 3, '2015-04-15', 4);
有没有办法将两个表中的数据组合在一起 点,我可以查询所有教授课程的教师的表格 某些员工?
-- Instructors who teach a class that has Ora Black in it.
select distinct cr.instructor_id
from class_rosters cr
inner join people p on p.p_id = cr.employee_id
where p.first_name = 'Ora' and p.last_name = 'Black';
-- Instructors who teach a class that has both Ora Black
-- and Robin Mings (an instructor) in it.
with students as (
select p_id
from people
where (first_name = 'Ora' and last_name = 'Black')
or (first_name = 'Robin' and last_name = 'Mings')
)
select instructor_id
from class_rosters cr
inner join students s on s.p_id = cr.employee_id
group by course_id, instructor_id, start_date
having count(*) = (select count(*) from students);
instructor_id -- 3