我正在创建一个Access DB,用于学校的C#应用程序。我没有太多使用DB的经验,所以如果这听起来很愚蠢就会忽略它。我希望用户能够选择所有某个学生在我们IT部门拥有的课程。我们总共有大约30个,一个人在4年高中时可以拿到的最大值是15.现在我的DB有15个不同的列,每个用户可以拥有一个类。如何将其压缩到一列(如果有方法)?
答案 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列设置一个新表。每行代表学生所学的课程。也许添加更多列,例如:年/学期,年级等