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

时间:2010-03-19 13:26:27

标签: sql-server-2005 database-design hierarchical-data

注意

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

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

上下文

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

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

             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表示在该区域工作的雇员名单

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

  1. Divisions - >纺织,营销(PK = DivisionID)
  2. Departments - >人力资源,财务(PK = DeptID)
  3. Functions - >薪资,招聘,审计,税务,账户(PK = FunctionID)
  4. Employees - >所有员工的名单(PK = EmployeeID)
  5. 我认为问题在于存在多个多对多关系,即许多部门有许多部门,许多部门都有许多部门。

    问题

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

    • 让所有在营销部门的薪资职能部门工作的员工

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

    据我所知,我可以在Departments和Functions之间构建一个'Link / Junction'表,以便我可以检索哪些功能在哪些Departments中。但是,我仍然需要区分他们所属的部门。

    研究工作

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

7 个答案:

答案 0 :(得分:2)

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

  • 部门
  • 功能
  • 实体

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

  • 选项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可以使用。)

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

  • 选项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 :(得分:1)

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

没有值得它的数据库盐会处理一百万条记录,这是一个很小的数据库。

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

答案 2 :(得分:1)

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

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

的查询

您可以将位置中的ID设为可选关系

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

一个简单的例子是:

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

答案 3 :(得分:1)

当你是“初学者”:)时,在尝试使用数据库设计感到宾至如归之前要做的一件事是阅读关于规范化的内容,并完全理解所有正常形式,直至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 - 不清楚它是什么,这些不可互换;有点像实例和a之间的区别类)。

答案 4 :(得分:0)

尝试为每个实体提供一个自己的表格,例如

//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

答案 5 :(得分:0)

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

答案 6 :(得分:0)

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