如何摆脱数据库中的多个列?

时间:2009-04-08 21:18:18

标签: c# database database-design oledb

我正在创建一个Access DB,用于学校的C#应用​​程序。我没有太多使用DB的经验,所以如果这听起来很愚蠢就会忽略它。我希望用户能够选择所有某个学生在我们IT部门拥有的课程。我们总共有大约30个,一个人在4年高中时可以拿到的最大值是15.现在我的DB有15个不同的列,每个用户可以拥有一个类。如何将其压缩到一列(如果有方法)?

6 个答案:

答案 0 :(得分:18)

优秀的问题Lucas,这深入研究了数据库规范化的行为。

您已经认识到为什么有多个列来表示类的事实已经很糟糕,这已经表明您有很大的潜力。

如果我们想要添加新课程怎么办?现在我们必须添加一个全新的列。这方面几乎没有灵活性。

那么可以做些什么呢?

我们创建三个表。

一张桌子是给学生的:

Student
   |-------------------------|
   | StudentID | Student_Name|
   |-------------------------|
   |     1     |     John    |
   |     2     |     Sally   | 
   |     3     |     Stan    | 
   ---------------------------

一个表用于类:

Class
   ------------------------
   | ClassID  | Class_Name|
   ------------------------
   |    1     |   Math    |
   |    2     |   Physics |
   ------------------------

最后,一个表格保存了学生和班级之间的关系:

Student_Class
   -----------------------
   | StudentID | ClassID |
   -----------------------

如果我们想将John注册到Physics,我们会在Student_Class表中插入一行。

  INSERT INTO Student_Class (StudentID, ClassID) VALUES (1, 2);

现在,我们有一条记录说学生#1(John)正在参加2级(物理)。让Sally参加数学,Stan参加物理和数学。

  INSERT INTO Student_Class (StudentID, ClassID) VALUES (2, 1);
  INSERT INTO Student_Class (StudentID, ClassID) VALUES (3, 1);
  INSERT INTO Student_Class (StudentID, ClassID) VALUES (3, 2);

为了以可读的方式提取数据,我们将三个表连接在一起:

  SELECT Student.Student_Name, 
         Class.Class_Name 
  FROM Student, 
       Class, 
       Student_Class 
  WHERE Student.StudentID = Student_Class.StudentID 
       AND Class.ClassID = Student_Class.ClassID;

这会给我们一个这样的结果集:

  ------------------------------
  | Student_Name  | Class_Name |
  ------------------------------
  |    John       |  Physics   |
  |    Sally      |   Math     |
  |    Stan       |  Physics   |
  |    Stan       |   Math     |
  ------------------------------

这就是数据库规范化的工作原理。

答案 1 :(得分:4)

听起来您需要考虑normalizing数据库架构。

学生和班级之间有many-to-many relationship,许多学生可以参加很多课程,许多学生可以参加很多课程。处理此方案的最常用方法是使用junction table

像这样的东西

Student Table
-------------
id
first_name
last_name
dob

Class Table
-----------
id
class_name
academic_year

Student_Class Table
-------------------
student_id
class_id
year_taken

然后您的查询将加入表格,例如

SELECT
    s.last_name + ', ' + s.first_name AS student_name,
    c.class_name,
    sc.year_taken
FROM
    student s
INNER JOIN
    student_class sc
ON
    s.id = sc.student_id
INNER JOIN
    class c
ON
    sc.class_id = class.id
ORDER BY
    s.last_name, sc.year_taken

我要提到的一个建议是Access在连接查询时要求您使用括号,我相信这是因为它要求您指定加入它们的顺序。就个人而言,我觉得这很尴尬,特别是当我习惯于在没有设计师的情况下编写大量SQL时。在Access中,我建议使用设计器连接表,然后为您的目的修改生成的SQL。

答案 2 :(得分:4)

所以你有15列(例如class1,class2,class3 ...... class15)?

看起来你有一个经典的many-to-many relationship。您应该创建一个新表来关联学生和班级。

student { StudentID, StudentName ... }
classes { ClassID, ClassName ... }
student_classes { StudentID, ClassID }

如果您逐年跟踪课程,您也可以在关系中添加年份列:

student_classes { StudentID, Year, ClassID }

答案 3 :(得分:2)

这是一个正常的问题。实际上你问的是错误的问题。而不是问自己一个问题,你怎么能存储0个或更多的classes_taken?您需要为每节课带来哪些其他细节?例如。只是上课,或采集数据,结果等?

例如,考虑以下

之类的事情
table Student
 id int
 name varchar(25)
 ...

table classes
 id int
 name varchar(25)
 ...

table clases_taken
 student_id int (foreign key to student.id)
 class_id int (foreign key to class.id)
 data_started datatime
 result varchar(5)
 tutor_id int (foreign key to tutor.id)
 ...

答案 4 :(得分:2)

您不应该在数据库表中拥有类1,class2,class3,class4等列。你应该拥有的是一张相关的表格。你的结构将是这样的:

Student Table with the following columns
StudentID
StudentLastName
StudentFirstName 
(and so forth for all the data to describe a student)

然后

Course table with the following columns
CourseId
CourseName

然后

StudentCourse Table with the following columns
StudentId
CourseID
CourseDate

现在要找出这个人带的课程,你们一起加入这些表格。 类似的东西:

Select StudentID,StudentLastName,StudentFirstName, CourseName, CourseDate
from Student 
join StudentCourse on student. studentid = StudentCourse.StudentID
join Course on Course.courseID = StudentCourse.CourseID 

请阅读此链接以开始学习数据库基础知识: http://www.deeptraining.com/litwin/dbdesign/FundamentalsOfRelationalDatabaseDesign.aspx

答案 5 :(得分:1)

学生表中没有类列怎么样?使用student id和class id列设置一个新表。每行代表学生所学的课程。也许添加更多列,例如:年/学期,年级等