sql >> Database >  >> RDS >> Mysql

Wat is de manier om een ​​eenvoudige relationele database leraar-onderwerp-student-batch te ontwerpen?

Je mist een tabel waarin vakken en studenten worden gekoppeld (per punt 2):

// student [student_id] takes subject [subject_id]
takes(student_id, subject_id)

Merk op dat elke basistabel een bijbehorende verklaringssjabloon heeft voor verklaringen over de bedrijfssituatie, geparametreerd door kolomnamen -- het (karakteristieke) predikaat . De rijen die het predikaat waar maken, komen in de tabel. Merk op dat de tabeldefinitie eruitziet als een afkorting voor het predikaat.

// teacher [id] named [name] with email [email] teaches subject [subject_id]
teacher(id, name, email, subject_id)

// subject [id] named [name] is [description]
subject(id, name, description)

// student [id] named [name] lives at [location])
student(id, name, location)

// batch [id] at venue [venue] was taught by teacher [teacher_id] on date [date]
batch(id, venue, teacher_id, date)

// student-batch [id] reports student [student_id] being in batch [batch_id]
student-batch(id, student_id, batch_id)
// CHECK student [student_id] takes the subject that is taught by the teacher of batch [batch_id]

Omdat je hierover stom lijkt te zijn, zal ik het afleiden in termen van hoe we kunnen redeneren voor het ontwerp van tabellen, beperkingen en query's. Een manier om de beperking die je wilt uit te drukken, lijkt de hierboven becommentarieerde CHECK te zijn.

Om een ​​tabel, beperking of query in SQL uit te drukken, beslissen we eerst over het predikaat ervan. Dan kunnen we het predikaat omzetten in steno. Dan kunnen we de steno naar SQL converteren.

Predikaat:

student [student_id] takes the subject that is taught by the teacher of batch [batch_id]

Basistabelpredikaten gebruiken:

FOR SOME k.*, t.*, b.* (
    student_id = k.student_id AND batch_id = b.bid
AND student [k.student_id] takes subject [k.subject_id]
AND teacher [t.id] named [t.name] with email [t.email] teaches subject [t.subject_id] 
AND batch [b.id] at venue [b.venue] was taught by teacher [b.teacher_id] on date [b.date]
AND [k.subject_id] = [t.subject_id]
AND [t.id] = [b.teacher_id])

Met steno:

FOR SOME k.*, t.*, b.* (
    student_id = k.student_id AND batch_id = b.bid
AND takes(k.student_id, k.subject_id)
AND teacher(t.id, t.name, t.email, t.subject_id)
AND batch(b.id, b.venue, b.teacher_id, date)
AND k.subject_id = t.subject_id
AND t.id = b.teacher_id)

In een FROM vertegenwoordigt elke (mogelijk impliciete) alias een tabel zoals de gegeven basistabelnaam en/of subquery, maar met elke kolom in zijn waarde &predikaat hernoemd naar alias .kolom .

We krijgen de rijen die voldoen aan de EN van twee predikaten door de tabellen van de predikaten in SQL samen te voegen. Als we rijen willen die voldoen aan de EN van een voorwaarde, dan gebruiken we ON of WHERE in SQL.

Een SELECT-component retourneert rijen waarbij FOR SOME waarden van gestippelde kolommen de geretourneerde (niet-gedoteerde) kolommen gelijk zijn aan functies van gestippelde kolommen die voldoen aan het FROM-predikaat.

SQL:Vervang instructies door hun tabellen, AND door JOIN of ON of WHERE, en outer FOR SOMMIGE &ER BESTAAT door SELECT:

SELECT t.student_id AS student_id, b.bid AS batch_id
FROM takes k JOIN teacher t JOIN batch b
WHERE k.subject_id = t.subject_id
AND t.id = b.teacher_id
AND student_id = t.student_id
AND batch_id = b.id

De tabel met rijen die voldoen aan de OR van twee predikaten is de UNION van hun tabellen. Voor AND NOT gebruiken we BEHALVE (ook bekend als MINUS) (of een LEFT JOIN-idioom). FOR SOMMIGE of ER BESTAAT over alle kolommen kan niet worden opgevraagd in SQL, maar als we willen weten of er rijen zijn die aan een predikaat voldoen, dan kunnen we EXISTS gebruiken rond een subquery met dat predikaat.

Stel dat we een basistabel willen beperken zodat elke rij op sommige kolommen voldoet aan een predikaat. Dwz VOOR ALLE kolommen ALS ze voldoen aan het basispredikaat DAN voldoen ze aan het querypredikaat. Dwz VOOR ALLE kolommen ALS de rij die ze vormen zich in de basis bevindt, DAN staat deze in de query. Dus we vereisen in SQL dat NIET BESTAAT (SELECTEER kolommen FROM base BEHALVE query). Of voor elke rij in de basis die we nodig hebben in SQL die BESTAAT(query).

In Standard SQL kon je ASSERTIE CONTROLE MAKEN (NIET BESTAAT (SELECT student_id, batch_id FROM student-batch BEHALVE query)) of in een CREATE TABLE student-batch die je zou kunnen CHECK(EXISTS(query)). Helaas worden deze niet ondersteund door MySQL of de meeste DBMS'en. Als je INSERT naar student-batch na batch, dan kun je bij trigger eisen dat dat BESTAAT (query). Of u kunt bepaalde kolommen en samengestelde FK-beperkingen (buitenlandse sleutel) toevoegen.

Nu zijn we een query aan het schrijven. We willen rijen waar:

FOR k.*, t.*, b.*, s.*, sb.* (
    batch = b.id AND teacher = t.name AND student = s.name
AND takes(k.student_id, k.subject_id)
AND teacher(t.id, t.name, t.email, t.subject_id)
AND batch(b.id, b.venue, b.teacher_id, b.date)
AND student(s.id, s.name, s.location)
AND student-batch(sb.id, sb.student_id, sb.batch_id)
AND k.subject_id = t.subject_id
AND t.id = b.teacher_id
AND s.id = k.student_id
AND sb.student_id = k.student_id
AND sb.batch_id = b.id
AND @date = b.date)

Dit lijkt op het constraint-predikaat met verschillende retourkolommen en toegevoegde regels. De SQL is net zo direct vertaald. We voegen een join toe met student om namen van studenten te krijgen. We voegen een join toe met student-batch omdat de beperking er niet mee te maken heeft; de contexten die de constraint-query gebruiken, controleren of student-batch (student_id, batch_id) subrijen erin staan.

SELECT b.id AS batch, t.name AS teacher, s.name AS student
FROM takes k JOIN teacher t JOIN batch b JOIN student s JOIN student-batch sb
WHERE ... AND @date = date

Je zou een ON-versie kunnen proberen:

SELECT b.id AS Batch, t.name AS Teacher, s.name AS Student
FROM takes k
JOIN teacher t ON k.subject_id = t.subject_id
JOIN batch b ON t.id = b.teacher_id
JOIN ...
WHERE @date = b.date



  1. Controleer twee datum was niet tussen twee andere datums + MYSQl

  2. Dynamisch selectievakjes maken

  3. Welke effecten heeft het gebruik van een binaire sortering?

  4. Hoe een afbeelding op te slaan in de kolom SQL Server-databasetabellen