用于递归关系的数据库设计

考虑这种情况下,我试图为公司建立数据库模型:

  • 实体: EmployeesManagersDepartments
  • 一个Employee只有1工作Department ,同时一个Department可能有许多Employees在正常工作。
  • Manager可能只管理一个Department ,同样一个Department可能只有一个Manager
  • Manager监督许多Employees ,但Employee只能由一位Manager监督。
  • 现在我有两种方法来模拟这个:

    第一解

    考虑到我将保留经理人特有的数据(例如奖金和状态),我会考虑Manager实体从Employee实体继承。

    第一个方案

  • 由于DepartmentEmployee之间的关系是1:N因此我将Department Id作为Works关系的Employee表中的外键。

  • 由于DepartmentManager之间的关系是1:1因此我将Department Id作为Manages关系的Manager表中的外键。

  • 问题:如何表示ManagerEmployee之间的递归关系?


    第二种方案

    我会考虑Manager实体不需要,因为其他Employees也可能有BonusStatus 。 (其实我加了这两个属性只是为了看看如何在两种情况下建模) 第二种方案

  • 由于DepartmentEmployee之间的关系是1:N因此我将Department Id作为Works关系的Employee表中的外键。
  • 由于EmployeeManager之间的关系是1:N我将Employee Id作为外部关键字放入Supervises关系的Employee表中,并将其称为Manager Id
  • 问题:如何表示ManagerDepartment之间的关系?


    问题:

  • 两种设计都有明显的错误吗?
  • 如何在两种情况下解决每个问题?
  • 有没有比这两个更好的解决方案?

  • 我可能会用类似的东西:

    在这里输入图像描述

    该模型具有以下特点:

  • 经理“继承”员工。
  • 要代表员工,请在EMPLOYEE中插入一行。
  • 为了表示一个经理,插入EMPLOYEE中的一行 MANAGER一行。
  • 一个部门可以有多个员工。
  • 每个部门只有1个经理,每个经理管理0个或1个部门。
  • 主管可以是普通员工或经理。
  • 部门不需要“匹配”:
  • 监督员可以在受监督员工的不同部门工作。
  • 经理可以管理他工作的不同部门。
  • 如果主管是经理,那么他所管理的部门,他所在的部门和他/她的受监管员工的部门都可能不同。
  • 注意:如果您的DBMS不支持延迟约束,您需要使DEPARTMENT.MANAGER_ID为NULL,以打破循环,否则会妨碍您插入新数据。


    如果部门需要匹配,那么您要么采用特定于DBMS的技术(例如触发器或“特殊”约束),要么将DEPARTMENT_ID“传播”到员工的PK中。 这种传播最终实现了匹配:

    在这里输入图像描述

    由于EMPLOYEE_ID必须是全局唯一的,因此它不能与DEPARTMENT_ID一起保留在组合键中。 因此,我们使用备用密钥,而使用PK中的代理EMPLOYEE_NO。

    这种模式可以防止你拥有一个管理一个部门并在另一个部门工作的经理,或者一个监督来自不同部门的员工的主管。


    如果您不熟悉符号...

    ...它表示一个“类别”。 在这种情况下,您可以简单地将其解释为员工与经理之间的“1比0或1”关系。


    在不详细说明的情况下,我确实向你保证,从长远来看,员工/经理/部门解决方案对于负责维护数据库的负责人来说(首先)是一个真正的PITA(稍后) /或开发其界面。 所以我建议你坚持你的第二个建议。

    关于经理/部门关系,主要有两种方式来表示这种关系。 这两种解决方案都授权您保留递归的“经理管理员工”关系,以及可以实施的“经理管理部门”关系,如下所示:

    1 - 第一/简单的方法:在部门表中添加经理/员工ID。 该字段当然是员工表的外键

    2秒/更复杂的解决方案:添加一个包含以下字段的“经理”表:

    Manager id (PK, surrogate)
    Department id (FK)
    Employee id (FK)
    beginningDate
    endingDate
    

    你将在哪里存储管理历史:谁,哪个部门,从何时到何时

    在这种情况下,不要忘记添加一些逻辑(触发器或客户端控制)来翻译您的业务规则,例如您可以只有一个经理在特定的时间段和特定的部门,任何部门都不能停留超过...没有经理等

    编辑:

    3 - 更丰富的解决方案将是我的第二个提议的概括,并且可以让您跟踪每个人在公司中的职业生涯。 你可以用一个'作品'表做这个,比如这个(我们在这里称之为“位置”表,我会在这里保留相同的术语:

    Position id (PK, surrogate)
    Department id (FK)
    Employee id (FK)
    Position Level (FK)
    beginningDate
    endingDate
    

    “职位级别”会导致另一个表格持有部门中可能存在的不同职位,其中之一当然是“经理”职位。

    该建议与HR数据库和软件中使用的建议更接近,并且您可能不需要如此复杂的解决方案。 但请记住,将人分成多个表格总是一个错误。

    编辑:关注你的评论...

    为了说清楚,我建议你调整你的字段名称。 我建议你有以下领域:

    Tbl_Employee.id_EmployeeManager
    

    Tbl_Department.id_DepartmentManager
    

    为此,我们(或任何开发人员)会立即明白id_EmployeeManager参与人员之间的递归关系,而id_DepartmentManager参与人员和部门之间的关系。

    回到你的问题,并根据我,你不应该创建以下链接:

    Tbl_Department.id_DepartmentManager -> Tbl_Employee.id_EmployeeManager
    

    通过这样做,你意味着有人不能成为部门经理, 除非他已经在管理员工。 有一名员工的部门呢? 那些新创建的部门的经理人员又如何分配? 这是行不通的。 正确的链接应该是:

    Tbl_Department.id_DepartmentManager -> Tbl_Employee.id_Employee
    

    您当然可以添加一些业务规则,例如“管理部门的员工只能成为经理”(id_Employee存在id_EmployeeManager某处)或“管理部门的员工无法拥有经理(其中该员工的id_EmployeeManager为null ......)但这些只是业务规则,只要基本规则得到遵守,您的数据模型就可以接受所有规则,这就是说部门由员工管理!


    我认为这是最好的解决方案:

    经理是管理部门的员工。 您可以通过下一个流程获得递归关系:

    员工有一个部门一个部门有一个员工作为经理

    也许可以方便地给员工表一个EmployeeType列来定义角色。

    链接地址: http://www.djcxy.com/p/70623.html

    上一篇: Database design for a recursive relationship

    下一篇: Database structure based on post type