1

我们正在创建一个应用程序来管理员工。员工可以是当前员工或未来将加入的员工(预测)。

除了管理员工外,我们还必须每月管理预测。

假设今天是四月,

截至 4 月 26 日,当前员工人数为 100。

今天,我预计 8 月将有 10 人加入。20 将于 11 月加入。

当我说我预测时,我实际上会在系统中添加 10 和 20 名员工。我可能有也可能没有完整的信息。我什至可能没有名字,因为他们还没有被雇用。但我只是预测,8 月将有 10 名员工,11 月将有 20 名员工,与 4 月一样。

假设中间没有更多的离开者或加入者。到 8 月底,我的员工人数将达到 110 人,到 11 月底将达到 130 人。

所以,8 月的 110 和 11 月的 130 是我对 4 月份的预测。

现在,在 5 月,我知道 8 月加入的不是 10 名,只有 5 名加入,11 月加入的不是 20 名,而是 25 名,另外我们将在 12 月解雇 10 名现有员工。

因此,我的员工人数预计在 5 月份将是 8 月的 105 人、11 月的 130 人和 12 月的 120 人。

因此,我需要按月保存员工数据,即我在 4 月对未来每个月的预测,即从 5 月到 12 月。

再说一次,我对 8 月到 12 月的预测是什么。

等等。

我还需要记住,现有员工的数据可能每分钟都在不断变化。

他们的头衔可能会改变,地址可能会改变,部门等。

因此,如果员工 A 在 4 月在 D1 部门,在 4 月之后在 D2 部门。

当我提取 4 月的报告时,它应该显示我为 D1,当我提取 6 月的报告时,它应该显示我他的部门为 D2。

请帮忙。


在上一个问题中有一些额外的背景。

编辑 :

请看下图。

我想知道每个后续月份中 3 月份(月份 = 3 月份)预测的员工人数,即月份 = 3 月份,3 月份的人数 = 400,4 月份的人数 = 405。

括号中的数字显示将在该月加入的新员工,例如 (+10) 和 (-5) 表示该月离职的员工。因此,如果 3 月份员工总数为 400 人,4 月份有 10 人加入,5 人离职,那么 4 月份的总人数将是 405 人。

在此处输入图像描述

4

3 回答 3

2

我可以看到您需要两个表的几个原因:

  • 真实员工必须有姓名、部门等,而预测员工可能只有这些属性
  • 会有只有真正的员工才能承担的职责,因此您希望能够单独引用它们

但同时您要确保两个表之间的 ID 没有冲突,因为(希望)预测员工将成为实际员工。

这样做的方法是实现一个超类型/子类型结构。因此,您有一个表 EMPLOYEES 保证单个主键,以及两个用于实际和预测员工的依赖表。类型列的使用至关重要,因为它确保给定的员工只出现在一个子表中。

create table employees
    ( emp_id number not null
      , emp_type varchar2(8) not null
      , constraint emp_pk primary key (emp_id)
      , constraint emp_uk unique (emp_id, emp_type)
      , constraint emp_type_ck check (emp_type in ('FORECAST', 'ACTUAL'));

create table actual_employees
    ( emp_id number not null
      , emp_type varchar2(8) not null
      , name varchar2(30) not null
      , deptno number(2,0) not null
      , sal number(7,2) not null
      , hiredate date not null
      , constraint actemp_pk primary key (emp_id)
      , constraint actemp_type_ck check (emp_type = 'ACTUAL')
      , constraint actemp_emp_fk foreign key (emp_id, emp_type)
                   references emp (emp_id, emp_type) 
                   deferrable initially deferred ;

create table forecast_employees
    ( emp_id number not null
      , emp_type varchar2(8) not null
      , name varchar2(30) 
      , deptno number(2,0) 
      , sal number(7,2) 
      , predicted_joining_date date
      , constraint foremp_pk primary key (emp_id)
      , constraint foremp_type_ck check (emp_type = 'FORECAST')
      , constraint foremp_emp_fk foreign key (emp_id, emp_type)
                   references emp (emp_id, emp_type) 
                   deferrable initially deferred ;

所以键可能看起来有点奇怪。父表同时具有主键和复合唯一键。主键保证 EMP_ID 的单个实例。唯一键允许我们在引用 EMP_ID 和 EMP_TYPE 的子表上构建外键。结合对子 t 的检查约束这是因为它们引用父表上的唯一键而不是其主键。这种安排能够确保员工可以在 FORECAST_EMPLOYEES 或 ACTUAL_EMPLOYEES 中,但不能同时在两者中。

外键是可延迟的,以允许将预测员工转换为实际员工。这需要三个活动:

  1. 从 FORECAST_EMPLOYEES 中删除记录
  2. 将记录插入 ACTUAL_EMPLOYEES
  3. 更改 EMPLOYEES 中的 EMP_TYPE(但不是EMP_ID)。

使用延迟约束同步操作 2 和 3 更容易。

另外,请注意引用 EMPLOYEES 的其他外键约束应该使用主键而不是唯一键。如果关系关心员工的类型,那么它可能应该链接到子表。


“有点头疼”

欢迎来到数据建模的世界。这是一个很大的头痛。因为试图将混乱的现实融入一个干净的数据模型是很困难的:你需要明确的要求才能让它正确,并且了解最重要的事情,这样你才能做出明智的妥协。

我根据您的另一个问题提出了一种超类型/子类型方法,因为这似乎是处理两组数据的最佳方法:真实员工和名义员工。我认为这两个群体需要区别对待。例如,我会坚持认为经理是真正的雇员。这很容易通过针对 ACTUAL_EMPLOYEES 的完整性约束来实现,而使用包含两种类型员工的单个表则更难实现。

肯定有两个表意味着在同步它们的结构方面可能会产生更多的工作。所以呢?这在很大程度上是微不足道的,因为编写两个 ALTER TABLE 语句的工作量几乎不比一个多。此外,新列很可能仅适用于实际员工,对预测员工没有意义(例如 EARNED_COMMISSION、LAST_REVIEW_RATING)。鉴于此,拥有单独的表格会使数据模型更加准确。

正如 Ollie 所指出的,关于必须复制依赖表,这是一种误解。适用于所有员工的表,无论其实际情况如何,都应该引用 EMPLOYEES 表而不是其子表。

最后我不明白为什么用两张表比一张表更难维护历史数据。大多数日志代码应该完全从数据字典中生成。


“如果我有 Employee 表和 Employee_forecast 表……”

共有三个表:

  • EMPLOYEES - 保证唯一 EMP_ID 的主表
  • ACTUAL_EMPLOYEES - 为贵公司工作的人员的子表
  • FORECAST_EMPLOYEES - 您希望招募到贵公司的人员的子表

“......他们的产品或活动都将存储在一个产品/活动表中?”

请记住,我是根据您提供的少量细节对您的业务逻辑做出假设。

现在在我看来,尚未为贵公司工作的人不应该有任何相关活动。在这种情况下,您将拥有一个表 EMPLOYEE_ACTIVITIES,它是 ACTUAL_EMPLOYEES 的子表。

但也许你确实为不存在的人提供活动。所以这里有一个选择:一张还是两张?单表设计将 EMPLOYEE_TASKS 作为主 EMPLOYEES 表的子表。这两个表设计分别将 ACTUAL_EMPLOYEE_TASKS 和 FORECAST_EMPLOYEE_TASKS 作为 ACTUAL_EMPLOYEES 和 FORECAST_EMPLOYEES 表的子表。

哪种设计是正确的取决于您是否需要强制执行有关任务分配的规则。例如,您的公司可能有一条规则,规定只有真人才能雇用新员工。因此,拥有一个只允许将招聘任务分配给 ACTUAL_EMPLOYEES 的模型会很有用。


“这个设计没有考虑月度预测”

好的,我已将日期列添加到两个表中。这将允许您运行所需的报告。

于 2012-04-26T12:22:32.693 回答
1

我认为您的数据模型将取决于您需要报告的信息。例如,我倾向于拥有标准EMPLOYEEDEPARTMENT表(如 Oracle 默认SCOTT模式)。

我还将有一个状态列,您可以在其中表示员工是当前员工或潜在员工,从而允许您报告当前雇用和预测雇用。您可以根据员工的状态等围绕需要哪些列添加功能约束/业务规则,因此当前员工将拥有全名、出生日期等,而潜在员工可能没有。

然后,我还将创建一个审计表来跟踪EMPLOYEE记录所经历的更改。这将允许您追溯查找他们的部门更改以及记录员工何时从潜在员工更改为当前员工等,以及对EMPLOYEE记录中其他数据的任何更改。
它还具有将所有数据保存在一个位置的优势。EMPLOYEE如果需要,您还可以考虑使用状态列对表进行分区。

这将使您受益于在您申请中的各个就业阶段的整个过程中只向每位员工颁发一个 ID。

状态栏的另一个好处是,您可以随后根据需要介绍员工可能经历的任何其他阶段。

编辑:

这也将确保如果您需要在将来添加列,如您所提到的,您只需要支持一个表结构。

于 2012-04-26T12:25:43.113 回答
0

这是我会做的: Employee 和 Department 表是典型的,但 emp 表中没有 dept_id 有一个 emp_dept 表来表示员工和部门之间的多对多,并具有关系的生效日期或生效日期范围。对于perspective_employees,我推荐一个单独的表,其中包含日期,然后在您需要该信息时与员工表联合。

在这里很难得到真正的详细信息,但我希望你能理解我所说的基础知识。

问候,罗杰

于 2012-04-26T11:45:23.633 回答