5

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

4

6 回答 6

18

很好的问题卢卡斯,这深入研究了数据库规范化的行为。

您认识到为什么使用多个列来表示类是不好的这一事实已经表明您具有巨大的潜力。

如果我们想添加一个新类怎么办?现在我们必须添加一个全新的列。对此几乎没有灵活性。

那么可以做些什么呢?

我们创建了三个表。

一张桌子是给学生的:

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

一张表用于类:

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

最后,一张表包含学生和班级之间的关系:

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

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

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

现在,我们有一个记录说学生#1(约翰)正在上班级#2(物理)。让莎莉上数学,斯坦上物理和数学。

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

简而言之,这就是数据库规范化的工作方式。

于 2009-04-08T21:31:37.853 回答
4

听起来您需要考虑规范化您的数据库模式。

学生和班级之间存在多对多的关系,因此许多学生可以选修许多课程,并且许多学生可以选修许多课程。处理这种情况的最常用方法是使用联结表

像这样的东西

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。

于 2009-04-08T21:25:27.307 回答
4

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

看起来你有一个经典的多对多关系。您应该创建一个新表来关联学生和班级。

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

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

student_classes { StudentID, Year, ClassID }
于 2009-04-08T21:25:49.973 回答
2

这是一个规范化问题。实际上,您问的是错误的问题。而是问自己一个问题,如何存储 0 个或多个 classes_taken?您还需要存储关于每节课的哪些其他详细信息?例如,只是上课,或数据,结果等?

例如考虑如下

表学生
 id int
 名称 varchar(25)
 ...

表类
 id int
 名称 varchar(25)
 ...

表 clases_taken
 student_id int (student.id 的外键)
 class_id int(class.id 的外键)
 data_started 数据时间
 结果 varchar(5)
 utor_id int(tutor.id 的外键)
 ...

于 2009-04-08T21:32:08.180 回答
2

您永远不应该在数据库表中包含 class1、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

于 2009-04-08T21:32:49.257 回答
1

学生表中没有班级列怎么样。设置一个包含学生 ID 和班级 ID 列的新表。每行代表学生上的一门课。也许添加更多列,例如:年/学期、年级等。

于 2009-04-08T21:21:26.553 回答