数据库架构问题

时间:2009-04-08 18:14:24

标签: database database-design schema

我很难决定如何处理数据库架构中的业务需求。我在数据库中有很多表,但是我只需要处理三个这个问题:课程,人事课程和人员。

  • 课程是课程列表
  • 企业人事 是人事列表
  • 人事课程是一系列课程 该人员采取

在课程中有一个名为Universal的专栏。如果课程是普遍的,那意味着所有人员必须参加该课程。

我需要生成人员必须采取的所有通用课程的列表,但我能够生成此列表的唯一方法是使用交叉连接/笛卡尔联接:

  

选择P.LastName,C.Name   来自C课程,人事P.   其中Universal = 1

由此我想在人员课程上进行左连接,这样我就可以列出他们必须采取的所有人员和课程以及他们所学的课程。我认为如果人事和课程之间有多对多的表格会更容易。但是,如果所有人员都要在这个中间表中,那不是有点多余吗?

有没有更好的方法来解决这个问题?

非常感谢,

-Matt

6 个答案:

答案 0 :(得分:3)

每个人都必须参加一系列课程。为什么不采用这个列表并使用它,而不是为每个人员行重复相同的列表?我不明白为什么你要试图乘以你的结果集。

答案 1 :(得分:1)

您的人事课程是不是在人与课程之间建立了多对多的关系?如果不是那么我不确定,如果是那么......

select *

from Personnel_Courses 
    inner join Person on... /*get the Person details*/
    inner join Courses on... /*get the Course details*/

where Course.Universal = 1 and Person.Id = @Id

会告诉你他们采取了哪些普遍课程......

然后

select *

from Courses

where Courses.Universal = 1 and Course.Id not in (
        select Course.Id from Personnel_Courses 
        inner join Person on... /*get the Person details*/
        inner join Courses on... /*get the Course details*/
        where Course.Universal = 1 and Person.Id = @Id
        )

会为你提供他们没有参加过的通用课程......

对我而言,在代码中执行第二步可能更容易(获取第一个查询结果,从“课程”表中执行选择以获得所有通用,然后进行比较...)

答案 2 :(得分:1)

这是一本书上写的主题Database Normalization  你想要这样做的部分原因是DRY或者不要重复。

所以回答你关于更好方法的问题 - 我会回答不。

答案 3 :(得分:0)

所有人员都不在人事课程表中,只有参加过课程的人员。

我认为你的设计很好。您只需要调整查询即可获得所需内容。

在子查询中拉出人员所采取的课程。然后在外部查询中选择人员必须执行的所有课程,并使用子查询执行左外连接。

Select a.CourseName, b.PersonName from Courses a, 
(select P.LastName, C.Name from Courses C, Personnel P, PersonnelCourses pc 
  c.courseid = pc.courseid and
  p.personnelid = pc.personnelid and
  c.Universal = 1)  b 
where
a.courseid += b.courseid order by courseid

如果是报告,最好按人员过滤。这样你就可以看到所需的所有课程,包括每人所需的课程。

答案 4 :(得分:0)

这样的事情(使用现有的结构)怎么样?

SELECT P.LastName, C.Name, 1 as Taken  
FROM Courses C   
  INNER JOIN PersonnelCourses PC ON (C.CourseID=PC.CourseID)  
  INNER JOIN Personnel P ON (P.PersonID=PC.PersonID)  
WHERE(C.Universal = 1)  

UNION  

SELECTP.LastName, C.name, 0 as Taken  
FROM Courses C, Personnel P   
WHERE (Universal = 1) and   
   NOT EXISTS(SELECT * FROM Courses C2 
             INNER JOIN PersonnelCourses PC2 ON (C.CourseID=PC.CourseID)
             INNER JOIN Personnel P2 ON (P.PersonID=PC.PersonID)
             WHERE (Universal = 1)  and 
                    (PC2.CourseID=C.CourseID) and       
                    (P2.PersonID=PC2.PersonID)
             )

答案 5 :(得分:0)

UniversalCourse的双值(布尔)属性,对吧?在这种情况下,请考虑进一步规范化。重新设计,以便UniversalCourse是一个表格,而不是Course上的一列。该表将有一个列引用该课程。要查找所有通用课程,只需从此表中选择所有内容即可。现在,您可以大大缩短笛卡尔连接,因为您必须将Personnel仅乘以UniversalCourse表,并取消where Universal = 1子句。