sql >> データベース >  >> RDS >> Mysql

複数のオプションを1つのテーブルに保存するにはどうすればよいですか?

    データの正規化 をお読みください 、一般的なインデックス作成 概念、および外部キー 参照整合性でデータをクリーンに保つための制約。これでうまくいきます。

    配列にデータを格納することは、紙の上では自然に思えるかもしれませんが、データベースエンジンにとっては、ほとんどの場合、インデックスを使用しない場合のパフォーマンスです。さらに、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の値に基づいてそのテーブルのデータの重複排除を強制する

    お持ち帰り

    重要な持ち帰り ジャンクションテーブルを使用すると、インデックスをすばやく取得でき、データとカンマ区切りのデータ(配列の考え方)を列に詰め込んだ状態で適切に管理できます。また、このような構成を使用することのすべての悲惨さもあります。



    1. Apache Sparkで点火する–パート1

    2. Oracleで日付が属する四半期を確認する

    3. パフォーマンスの神話:クラスター化インデックスと非クラスター化インデックス

    4. 2Dアレイから1Dアレイを選択するにはどうすればよいですか?