我们正在创建一个管理员工的应用程序。员工可能是未来的员工或将要加入的员工(预测)。
除了管理员工外,我们还必须按月管理预测。
假设今天是四月,
截至4月26日,员工人数为100人。
今天,我预计8月将有10人加入。 20将于11月加入。
当我说我预测我实际上会在系统中增加10和20名员工。我可能有也可能没有完整的信息。我甚至可能没有名字,因为他们还没有被录用。但我只是预测,8月将招聘10名,11月份将招聘20名。
假设中间没有更多的离职者或加入者。我到8月底的员工人数为110人,到11月底为130人。
所以,8月的110和11月的130是我在4月份的预测。
现在,5月份,我知道,8月而不是10年只有5人加入,11月而不是20年,25人将加入,加上我们将在12月解雇10名现有员工。
因此,我的员工数量预计可能在8月份为105人,11月份为130人,12月份为120人。
所以,我需要按月保持员工数据,即我在4月份预测的每个月,即从5月到12月。
再次,我在8月到12月的预测是什么。
等等。
我还需要记住,现有员工的数据可能每隔一分钟就会继续进行。
他们的头衔可能会改变,地址可能会改变,部门等。
因此,如果员工A在4月份在D1部门,在4月份之后是D2。
当我提出4月的报告时,它应该显示为D1,当我提出6月的报告时,它应该显示他的部门为D2。
请帮忙。
this previous question中还有一些其他背景信息。
编辑:
请参阅下图。
我想知道3月(月份= 3月)在每个后续月份中预测的员工人数,即月份= 3月,3月份计数= 400,4月份计算= 405.
括号中的数字表示将在该月加入的新员工,例如(+10)& (-5)显示员工在该月离职。因此,如果在3月份,总共有400名员工和10名员工加入,5名员工将在4月离职,那么4月份的总人数将为405人。
答案 0 :(得分: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,但不能同时处于两者之中。
外键可以推迟,以便将预测员工转换为实际员工。这需要三项活动:
使用延迟约束可以更轻松地同步动作2和3。
另请注意,引用EMPLOYEES的其他外键约束应使用主键而不是唯一键。如果关系关心员工的类型,那么它可能应该链接到子表。
"有点头疼"
欢迎来到数据建模的世界。这是一个令人头痛的问题。因为努力将凌乱的现实融入干净的数据模型 hard :你需要明确的要求才能做到正确,并了解最重要的事情,这样你才能做出合理的妥协。
我根据您的其他问题提出了超类型/子类型方法,因为它似乎是处理两组数据的最佳方式:真实员工和名义员工。我认为这两个群体需要区别对待。例如,我会坚持要求经理成为真正的员工。使用针对ACTUAL_EMPLOYEES的完整性约束很容易做到这一点,并且使用包含两种类型员工的单个表更难实现。
确实有两个表意味着可能会产生更多关于同步其结构的工作。所以呢?它很大程度上是微不足道的,因为编写两个ALTER TABLE语句而不是一个语句只需要更多的工作。此外,新列很可能仅适用于实际员工,对预测员工没有意义(例如EARNED_COMMISSION,LAST_REVIEW_RATING)。在这种情况下,具有单独的表使数据模型更准确。
关于必须复制依赖表,正如Ollie指出的那样,这是一种误解。适用于所有员工的表格,无论其实际情况如何,均应参考EMPLOYEES表而非其子女表。
最后,我不明白为什么用两张桌子维护历史数据比用一张桌子更难。大多数日记代码应该完全从数据字典中生成。
"如果我有Employee表和Employee_forecast表..."
有三个表:
" ...他们的产品或活动将存储在一个单一的产品或活动中 产品/活动表?"
请记住,我从您提供的细节中对您的业务逻辑做出假设。
现在在我看来,那些尚未为贵公司工作的人不应该有任何相关的活动。在这种情况下,您将拥有一个表EMPLOYEE_ACTIVITIES,它是ACTUAL_EMPLOYEES的子项。
但也许你确实为那些不存在的人做了活动。所以这是一个选择:一个或两个?一个表设计将EMPLOYEE_TASKS作为主EMPLOYEES表的子项。两个表设计分别将ACTUAL_EMPLOYEE_TASKS和FORECAST_EMPLOYEE_TASKS作为ACTUAL_EMPLOYEES和FORECAST_EMPLOYEES表的子项。
哪种设计是正确的取决于您是否需要执行有关任务授权的规则。例如,您的公司可能有一条规则,规定只有真正的人才能雇用新员工。因此,拥有一个仅允许将招聘任务分配给ACTUAL_EMPLOYEES的模型会很有用。
"此设计对月份没有任何考虑 预测"
好的,我已将日期列添加到两个表中。这将允许您运行所需的报告。
答案 1 :(得分:1)
我认为您的数据模型将取决于您需要报告的信息。
例如,我倾向于使用标准的EMPLOYEE
和DEPARTMENT
表(如Oracle默认的SCOTT
模式)。
我还有一个状态列,您可以在其中表示员工是当前员工或潜在员工,从而允许您报告当前员工和预测员工。您可以根据员工的状态等添加功能约束/业务规则,因此当前员工将拥有全名,DOB等,而潜在员工可能不会。
然后我还会创建一个审计表来跟踪EMPLOYEE
记录所经历的更改。这将允许您回顾性地查找他们的部门更改以及记录员工何时从预期员工更改为当前员工等,以及EMPLOYEE
记录中对其他数据的任何更改。
它还具有将所有数据保存在一个位置的优势。如果需要,您还可以考虑使用状态列对EMPLOYEE
表进行分区。
这样,您只需在申请过程中的各个阶段向每位员工发放一个ID,即可获得一个ID。
状态栏的另一个好处是,您可以在将来根据需要介绍员工可以经历的任何其他阶段。
修改强>
这也可以确保如果您将来需要添加列,您只需要支持一个表结构。
答案 2 :(得分:0)
这是我要做的: Employee和Department表是典型的,但在emp表中没有dept_id 有一个emp_dept表来表示员工和部门之间的多对多,表示关系的生效日期或生效日期范围。 对于perspective_employees,我建议一个单独的表,其中包含日期,然后在需要该信息时与employee表联合。
这里很难详细说明,但我希望你能得到我所说的基础知识。
此致 罗杰