我想设计一个用于结果计算的应用程序。

首先,我需要知道如何将记录存储在MySQL数据库中,这样学生可以附加尽可能多的类(class),例如学生A可以附加6个科目,而学生B可以附加12个科目。

在这种情况下,我需要知道如何设计一种数据库结构,该结构将允许字段以数组形式存储尽可能多的主题。

任何建议或更好的方法来解决此问题将不胜感激。

最佳答案

请仔细阅读Data NormalizationGeneral Indexing概念和Foreign Key约束,以保持数据完整性和参照完整性。这会带你去。
在纸上,将数据存储在数组中似乎很自然,但是对于db引擎,性能几乎没有索引的使用。此外,您会在第2天发现获取和维护数据是一场噩梦。
以下内容将使您在修补过程中有一个良好的开端。 Joins

create table student
(   studentId int auto_increment primary key,
    fullName varchar(100) not null
    -- etc
);

create table dept
(   deptId int auto_increment primary key,
    deptName varchar(100) not null -- Economics
    -- etc
);

create table course
(   courseId int auto_increment primary key,
    deptId int not null,
    courseName varchar(100) not null,
    -- etc
    CONSTRAINT fk_crs_dept FOREIGN KEY (deptId) REFERENCES dept(deptId)
);

create table SCJunction
(   -- Student/Course Junction table (a.k.a Student is taking the course)
    -- also holds the attendance and grade
    id int auto_increment primary key,
    studentId int not null,
    courseId int not null,
    term int not null, -- term (I am using 100 in below examples for this term)
    attendance int not null, -- whatever you want, 100=always there, 0=he must have been partying,
    grade int not null, -- just an idea
    -- See (Note Composite Index) at bottom concerning next two lines.
    unique key(studentId,courseId,term), -- no duplicates allowed for the combo (note student can re-take it next term)
    key (courseId,studentId),
    CONSTRAINT fk_sc_student FOREIGN KEY (studentId) REFERENCES student(studentId),
    CONSTRAINT fk_sc_courses FOREIGN KEY (courseId) REFERENCES course(courseId)
);
创建测试数据
insert student(fullName) values ('Henry Carthage'),('Kim Billings'),('Shy Guy'); -- id's 1,2,3
insert student(fullName) values ('Shy Guy');

insert dept(deptName) values ('History'),('Math'),('English'); -- id's 1,2,3

insert course(deptId,courseName) values (1,'Early Roman Empire'),(1,'Italian Nation States'); -- id's 1 and 2 (History dept)
insert course(deptId,courseName) values (2,'Calculus 1'),(2,'Linear Algebra A'); -- id's 3 and 4 (Math dept)
insert course(deptId,courseName) values (3,'World of Chaucer'); -- id 5 (English dept)

-- show why FK constraints are important based on data at the moment
insert course(deptId,courseName) values (66,'Fly Fishing 101'); -- will generate error 1452. That dept 66 does not exist
-- That error is a good error to have. Better than faulty data

-- Have Kim (studentId=2) enrolled in a few courses
insert SCJunction(studentId,courseId,term,attendance,grade) values (2,1,100,-1,-1); -- Early Roman Empire, term 100 (made up), unknown attendance/grade
insert SCJunction(studentId,courseId,term,attendance,grade) values (2,4,100,-1,-1); -- Linear Algebra A
insert SCJunction(studentId,courseId,term,attendance,grade) values (2,5,100,-1,-1); -- World of Chaucer

-- Have Shy Guy (studentId=3) enrolled in one course only. He is shy
insert SCJunction(studentId,courseId,term,attendance,grade) values (3,5,100,-1,-1); -- Early Roman Empire, term 100 (made up), unknow attendance/grade
-- note if you run that line again, the Error 1062 Duplicate entry happens. Can't take same course more than once per term
一些简单的问题。
什么部门在什么类(class)?
全部显示,使用表别名(缩写)来减少键入,提高可读性(有时)
select c.courseId,c.courseName,d.deptId,d.deptName
from course c
join dept d
on c.deptId=d.deptId
order by d.deptName,c.courseName -- note the order
+----------+-----------------------+--------+----------+
| courseId | courseName            | deptId | deptName |
+----------+-----------------------+--------+----------+
|        5 | World of Chaucer      |      3 | English  |
|        1 | Early Roman Empire    |      1 | History  |
|        2 | Italian Nation States |      1 | History  |
|        3 | Calculus 1            |      2 | Math     |
|        4 | Linear Algebra A      |      2 | Math     |
+----------+-----------------------+--------+----------+
这学期谁在上乔科世界类(class)?
(知道courseId = 5)
以下内容受益于我们在SCJunction中的综合指数之一。组合是在多个列上的索引。
select s.StudentId,s.FullName
from SCJunction j
join student s
on j.studentId=s.studentId
where j.courseId=5 and j.term=100
+-----------+--------------+
| StudentId | FullName     |
+-----------+--------------+
|         2 | Kim Billings |
|         3 | Shy Guy      |
+-----------+--------------+
金比林斯(King Billings)参加了这个学期的类(class)?
select s.StudentId,s.FullName,c.courseId,c.courseName
from SCJunction j
join student s
on j.studentId=s.studentId
join course c
on j.courseId=c.courseId
where s.studentId=2 and j.term=100
order by c.courseId DESC -- descending, just for the fun of it
+-----------+--------------+----------+--------------------+
| StudentId | FullName     | courseId | courseName         |
+-----------+--------------+----------+--------------------+
|         2 | Kim Billings |        5 | World of Chaucer   |
|         2 | Kim Billings |        4 | Linear Algebra A   |
|         2 | Kim Billings |        1 | Early Roman Empire |
+-----------+--------------+----------+--------------------+
Kim不知所措,所以放弃了数学课
delete from SCJunction
where studentId=2 and courseId=4 and term=100
在选择语句上方运行该语句,以显示Kim正在采取的措施:
+-----------+--------------+----------+--------------------+
| StudentId | FullName     | courseId | courseName         |
+-----------+--------------+----------+--------------------+
|         2 | Kim Billings |        5 | World of Chaucer   |
|         2 | Kim Billings |        1 | Early Roman Empire |
+-----------+--------------+----------+--------------------+
嗯,这个词更容易理解。爸爸虽然不会高兴。
注意诸如SCJunction.term之类的东西。关于这点可以写很多,我现在大部分时间会跳过它,而不是说它也应该在FK的某个地方。您可能希望您的术语看起来更像是SPRING2015,而不是int。
就ID而言。这就是我要做的方式。这是个人喜好。它将需要知道id#,然后查找它们。其他人可能会选择一个具有HIST101之类的courseId而不是17的人。它们具有更高的可读性(但索引速度较慢(勉强))。因此,对您来说最好的方法就是这样做。
票据综合指数
复合索引(INDEX表示KEY,反之亦然)是一种组合多列以进行快速数据检索的索引。翻转SCJunction表中两个组合的顺序,以便db引擎根据要追随数据的查询范围,可以根据要追寻的最左边的列选择用于快速检索的索引。
至于唯一 key #1,它旁边的注释表明不重复(意味着垃圾数据),这是不言自明的。例如,该表中不能存在两次学生1类(class)1术语1。
要理解的一个关键概念是索引中列名的left-most排序的概念。
对于仅在studentId 之后进行的查询,则使用首先列出studentId的键(left-most)。在只在courseId 之后进行的查询中,仅使用最左边的键。在studentId和courseId之后的查询中,数据库引擎可以决定要使用哪个组合键。
当我说“go after”时,是指courseIdon clause条件。
如果不让这两个复合键(其中的第1列和第2列翻转),那么在查询中未对where clause索引的列进行索引的查询中,您将不会受益于键的使用,并且需要进行慢速的表扫描以返回数据。
因此,这两个索引结合了以下两个概念
  • 基于最左端或两者(studentId和courseId列)的快速数据检索
  • 基于studentId,courseId和term值强制对该表中的数据进行非重复

  • 外卖
    重要的要点是,Junction表可以快速检索索引,并且将数据与逗号分隔的数据(数组思维方式)的理智管理塞入一列,以及使用这种构造的所有痛苦。

    10-05 18:16