首页 文章

SQL Server 2005数据库设计 - 与层次结构的多对多关系

提问于
浏览
6

Note

我完全重写了我原来的帖子,以便更好地解释我想要了解的问题 . 我试图尽可能地概括这个问题 .

另外,我要感谢回应的原始人 . 希望这篇文章能让事情变得更加清晰 .

Context

简而言之,我正在努力理解设计小规模数据库以处理(我认为是)多个多对多关系的最佳方法 .

想象一下公司组织结构的以下场景:

Textile Division                    Marketing Division
                    |                                     |
          ----------------------               ----------------------
          |                    |               |                    |
       HR Dept           Finance Dept        HR Dept           Finance Dept
          |                    |               |                    |
      ----------          ----------       ----------           ---------
     |          |         |        |       |        |           |       |
  Payroll     Hiring    Audit     Tax   Payroll   Hiring      Audit  Accounts
     |          |         |        |       |        |           |       |
    Emps      Emps       Emps     Emps    Emps     Emps        Emps    Emps

注意: Emps 表示在该区域工作的雇员名单

当我第一次开始这个问题时,我做了四个单独的表:

  • Divisions - >纺织,营销(PK = DivisionID)

  • Departments - >人力资源,财务(PK = DeptID)

  • Functions - >薪资,招聘,审计,税务,账户(PK = FunctionID)

  • Employees - >所有员工列表(PK = EmployeeID)

我认为问题在于存在多个多对多关系,即许多部门有许多部门,许多部门有很多部门 .

Question

给出上面的数据库结构,假设我想要执行以下操作:

  • 获取在营销部门的薪资功能中工作的所有员工

为此,我需要能够区分两个薪资部门,但我不确定如何做到这一点?

我知道我可以在Departments和Functions之间 Build 一个'Link / Junction'表,这样我就可以检索哪些部门的功能 . 但是,我仍然需要区分他们所属的部门 .

Research Effort

正如您所看到的,在数据库设计方面,我是一名初学者 . 我花了最近两天来解决这个问题,遍历嵌套集模型,邻接模型,读取这个问题已知不是NP完全等等 . 我确信有一个简单的解决方案?

7 回答

  • 0

    基于更新后的帖子,并基于所使用的名称做出一些(相当明显的)假设,我想出了以下内容 . 有四个实体:

    • 分部

    • 部门

    • 功能

    • 实体

    这些实体之间存在许多关系 . 其中很少是等级的,大多数都是简单的联想:

    • 选项A1:有一个主要的功能列表 . 每个部门都可以执行(或执行)一个或多个功能,并且可以由多个部门执行功能 .

    • 选项A2:各部门“拥有”职能 . 两个或更多部门无法执行任何功能 . (情况似乎如此,因为人力资源部门有薪资和招聘,财务部门有审计,税务和账户 . )

    • 各部门(代表)各部门履行职能 . (人力资源部负责纺织和营销部门的薪资和招聘;财务部负责纺织部门的审计和税务 - 但不包括账户 - 审计和账户 - 但不包括营销部门的税务 . )也许有点更准确地说,部门为与之关联的所选部门执行选定的功能,并且该关联由其功能的性能定义 .

    • 除了履行职能部门之外,部门和部门之间似乎没有任何关系 . 它们之间没有层次关系,因为一个人不“拥有”或包含另一个 .

    这导致了这些大致草拟的表格:

    --  Division  -----
    DivisionId  (primary key)
    
    --  Department  ---
    DepartmentId  (primary key)
    
    --  Function  -----  (assumes option A2)
    FunctionId   (primary key)
    DepartmentId (foreign key, references Department)
    
    --  DivisionFunctions  ----
    DivisionId  (First column of compound primary key)
    FunctionId  (Second column of compound primary key)
    

    (您可以选择包含一个代理键来唯一标识每一行,但DivisionId FunctionId可以工作 . )

    这里没有足够的材料来充分描述"employees"如何适应模型 . 鉴于员工从事的是职能部门的工作:员工可以完成多项职能的工作,还是只做一项职能?员工是否负责该职能的工作,无论其所处的职责是什么,或者他们是否被指派为一个或多个部门工作?这里有两个明显的选择,但更复杂的变体是可能的:

    • 选项B1:员工在部门内完成一项或多项职能的工作,并为需要该部门职能的所有部门执行该工作 .

    • 选项B2:指定员工为特定部门执行特定功能 .

    鉴于这些,表可能看起来像:

    --  Employee  -----  (assumes option B1)
    EmployeeId    (primary key)
    DepartmentId  (foreign key, references Department)
    
    --  EmployeeFunction  -----  (assumes option B1)
    EmployeeId  (First column of compound primary key)
    FunctionId  (Second column of compound primary key)
    

    ......因此,所有能够执行功能的员工都会为需要它的所有部门执行该功能 . 要么,

    --  Employee  -----  (assumes option B2)
    EmployeeId  (primary key)
    DepartmentId  (foreign key, references Department)
    
    --  EmployeeAssignment  -----  (assumes option B2)
    EmployeeId  (foreign key, references Employee)
    DivisionId  (first of two-column foreign key referencing DivisionFunctions)
    FunctionId  (second of two-column foreign key referencing DivisionFunctions)
    

    (或者,而不是DivisionId和FunctionId,包括来自DivisionFunctions的可选代理键 . )...因此,员工被单独分配给部门为部门执行的功能 .

    但这仍然留下了很多“如果/何时”的问题:员工“属于”部门吗?员工可以属于(为多个部门工作)吗?也许员工属于分部?您是否跟踪员工可以执行哪些功能,即使他们目前没有这样做?同样,你跟踪员工在哪个部门工作,即使他们目前“在职能部门之间”?如果员工可以执行功能A和B,并且某个部门需要这两个功能,那么员工是否可以被分配为仅为该部门执行A而不是B?

    这里有更多的需求研究要做,但我想这是一个好的开始 .

  • 1

    好吧,你不会把它全部放在一张 table 里 . 您需要阅读规范化数据和连接 . (永远不要在逗号分隔列表中存储任何内容 . )

    没有数据库值得它的盐会有最轻微的问题处理一百万条记录,这是一个很小的数据库 .

    您需要用于功能,课程,位置,人员,组织以及可能的一些连接表的表,以适应多对多的关系 . 但这一切都不是很难,甚至超出了非常基本的设计 . 我建议您在执行任何操作之前,先阅读所选数据库的书籍并阅读基础知识 .

  • 0

    你需要一个简单的 star 关系 . 位置(事实表)只有相关主表的ID(部门,部门等) . 这允许使用主表的任何组合

    主表可以根据需要在每个主表中构建简单的层次结构 . 并且可以根据需要相互关联 . 但是详细信息不会影响对Position的查询

    对于可选关系,您可以将ID设置为位置可空

    您可以将StartDate和EndDate列添加到Position以跟踪随时间的变化

    一个简单的例子是:

    SQL Table Diagram http://img52.imageshack.us/img52/3484/sqldiag1.jpg

  • 0

    因为你是"abecedarian" :),在尝试在家中使用数据库设计之前要做的一件事是关于规范化,并完全理解所有正常形式,直到5NF

    如果你想模仿那个
    部门是分部的
    2.职能在部门执行
    3.员工履行职能

    并且并非所有功能都在所有部门中执行,也不是所有部门都在所有部门中,那么您必须将该事实存储在某个地方 .

    在进行逻辑设计时,请为表格提供描述性名称,以便某些部门处于分支状态

    departments_in_divisions
    candidate key: department, division
    

    那么你在某些部门有一些功能

    functions_departments_divisions
    candidate key: function, department, division
    references: (department, division) in departments_divisions
    

    然后,员工可以从一些部门和部门获得一些职能

    employees_function_department_division
    candidate key: employee, function, department, division
    references: (function, department, division) in functions_departments_divisions
    

    在此之后(或之前),您还有3个实体函数,部门和部门,它们将列出上述表格也会引用的所有可能的部门,部门和职能(这可能没有完全标准化) .

    此外,实体(表)的名称可以变得更适合您(只有您可以知道数据模型的完整语义) . 特别是如果您注意到需要为其分配其他属性(字段) .

    部门,部门和职能部门的名称是他们的名字,在上面的分析中还没有人工设备 . 在逻辑建模进行物理建模之后,您可以在下一步中介绍它们,或者您可以保留自然键 . 如果使用可以将复合键的使用量减少到最大2的人工键,但它会混淆您在表中存储的事实的关系和含义 . (示例functionID可以是函数名称的ID,也可以是在某个部门/部门组合中执行的函数的ID - 不清楚它是什么,这些不可互换;有点像实例和实例之间的区别类) .

  • 1

    尝试给每个实体一个自己的表格,例如

    //Table Structure
    location
        locationId
        name
    
    division
        divisionId
        name
        locationId (fk => location)
    
    department
        deparmentId
        name
        divisionId (fk => division)
    
    function
        functionId
        name
        departmentId(fk => department)
    
    jobrole
        jobroleId
        name
        functionId
    
    course
        courseID
        name
    
    jobrole_course_requirement
        jobroleID
        courseID
    
    employee
         employeeID
         name
    
    employee_jobRole
         employeeID
         jobRoleId
    
    emploeyee_course_attendance
         emploeyee_course_attendanceID
         emploeyeeID
         courseID
         dateAttended
    

    一些样本选择

    // Get course requirements for an employee
    select course.name 
      from course, 
           jobrole_course_requirement, 
           employee_jobRole
      where 
           employee_jobRole.employeeID = 123 and
           jobrole_course_requirement.JobRoleId = employee_jobRole.JobRoleId
           course.courseID = jobrole_course_requirement.courseID
    
  • 2

    通常在我 Build 数据库时,我想出了我需要的实体以及它们如何相互关联(即多对一,一对......) . 你似乎已经做了什么 . 接下来我会弄清楚每个实体需要什么 . 例如,位置可能具有:locationid,address,...然后,分部假设每个分区有一个位置,您可以让分区实体具有divisionid,locationid,每个分区需要的信息 . 所以基本上,如果它是一个多关系,就像一个位置到多个部门,你可以把位置的id放在除法表中 . 但是,如果它是一个多关系,那么最好有一个中间表来连接这两个,这样你就不需要只有id更改的重复记录 .

  • 1

    也许(可能)您应该将纺织部门的人力资源部门视为与市场部门人力资源部门不同的部门 .

相关问题