データの正規化 をお読みください 、一般的なインデックス作成 概念、および外部キー 参照整合性でデータをクリーンに保つための制約。これでうまくいきます。
配列にデータを格納することは、紙の上では自然に思えるかもしれませんが、データベースエンジンにとっては、ほとんどの場合、インデックスを使用しない場合のパフォーマンスです。さらに、2日目には、データの取得と維持が悪夢になることがわかります。
以下は、いじくり回しながら良いスタートを切ることができるはずです。 参加
も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
いくつかの簡単な質問。
どの部門にどのコースがありますか?
すべて表示、テーブルエイリアス(省略形)を使用して、入力を減らし、読みやすさを(場合によっては)向上させます
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 |
+----------+-----------------------+--------+----------+
今期、チョーサーの世界コースを受講するのは誰ですか?
(courseId =5を知っている)
以下は、SCJunctionの複合インデックスの1つから恩恵を受けています。コンポジットは、複数の列のインデックスです。
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 |
+-----------+--------------+
キムビリングスは今期何に登録されていますか?
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 |
+-----------+--------------+----------+--------------------+
キムは圧倒されているので、数学の授業をドロップドロップしてください
delete from SCJunction
where studentId=2 and courseId=4 and term=100
キムが取っているものを示す上記のselectステートメントを実行します:
+-----------+--------------+----------+--------------------+
| StudentId | FullName | courseId | courseName |
+-----------+--------------+----------+--------------------+
| 2 | Kim Billings | 5 | World of Chaucer |
| 2 | Kim Billings | 1 | Early Roman Empire |
+-----------+--------------+----------+--------------------+
ああ、はるかに簡単な用語。お父さんは幸せではありません。
SCJunction.termなどに注意してください。それについては多くのことが書かれていますが、FKのどこかにあるべきだと言う以外は、現時点ではほとんどスキップします。用語をintではなくSPRING2015のように見せたい場合があります。
そして、idが行く限り。これは私がそれをする方法です。個人的な好みです。 ID番号を知り、それらを検索する必要があります。他の人は、17ではなくHIST101のようなcourseIdを選択することができます。それらは非常に読みやすくなっています(ただし、インデックスの速度は遅くなります(ほとんどありません)。したがって、自分に最適な方法を実行してください。
ノートコンポジットインデックス
複合インデックス(INDEXはKEYを意味し、その逆も同様)は、複数の列を組み合わせてデータを高速に取得するためのインデックスです。 SCJunctionテーブル内の2つのコンポジットの順序が反転されるため、データを追跡するクエリの範囲に応じて、データベースエンジンは、追跡する左端の列に基づいて、最速の取得に使用するインデックスを選択できます。 。
一意のキー#1については、その横にある、重複(ジャンクデータを意味する)を強制しないというコメントは、かなり自明です。たとえば、学生1コース1ターム1は、そのテーブルに2回存在することはできません。
理解しておくべき重要な概念は、left-most
の概念です。 インデックス内の列名の順序。
studentId
の後に続くクエリの場合 のみ 、次にstudentId
を持つキー 最初にリストされています(left-most
) 使用されている。 courseId
の後に続くクエリ のみ 、次にcourseId
を持つキー 左端が使用されます。 StudentIdとcourseIdの両方を追跡するクエリでは、dbエンジンが使用する複合キーを決定できます。
私が「後を追う」と言うとき、私はon clause
を意味します またはwhere clause
状態。
これらの2つの複合キー(列1と2が反転している)がない場合は、検索する列がleft-most
ではないクエリで インデックスが作成されていると、キーを使用してもメリットがなく、データを返すためのテーブルスキャンが遅くなります。
したがって、これら2つのインデックスは、次の2つの概念を組み合わせたものです
- 左端または両方(studentId列とcourseId列)に基づく高速データ取得
- studentId、courseId、termの値に基づいてそのテーブルのデータの重複排除を強制する
お持ち帰り
重要な持ち帰り ジャンクションテーブルを使用すると、インデックスをすばやく取得でき、データとカンマ区切りのデータ(配列の考え方)を列に詰め込んだ状態で適切に管理できます。また、このような構成を使用することのすべての悲惨さもあります。