sql >> Databáze >  >> RDS >> Mysql

Jaký je způsob návrhu jednoduché relační databáze učitel-předmět-žák-dávka?

Chybí vám tabulka sdružující předměty a studenty (podle bodu 2):

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

Všimněte si, že každá základní tabulka má přidruženou šablonu prohlášení pro prohlášení o obchodní situaci, parametrizovanou názvy sloupců – jejich (charakteristickým) predikátem . Řádky, které činí predikát pravdivým, jsou v tabulce. Všimněte si, že definice tabulky vypadá jako zkratka pro predikát.

// 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]

Vzhledem k tomu, že se vám to zdá zaskočené, odvodím to z hlediska toho, jak můžeme zdůvodnit návrh tabulky, omezení a dotazu. Jedním ze způsobů, jak vyjádřit požadované omezení, se zdá být komentovaná KONTROLA výše.

Abychom vyjádřili jakoukoli tabulku, omezení nebo dotaz v SQL, nejprve se rozhodneme pro jejich predikát. Potom můžeme predikát převést na těsnopis. Poté můžeme zkratku převést na SQL.

Predikát:

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

Použití predikátů základní tabulky:

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])

Použití zkratek:

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)

V FROM každý (možná implicitní) alias představuje tabulku, jako je daný název základní tabulky a/nebo poddotaz, ale každý sloupec ve své hodnotě a predikátu je přejmenován na alias .sloupec .

Řádky splňující AND dvou predikátů získáme spojením tabulek predikátů v SQL. Pokud chceme řádky splňující AND podmínky, použijeme ON nebo WHERE v SQL.

Klauzule SELECT vrací řádky, kde PRO NĚKTERÉ hodnoty tečkovaných sloupců jsou vrácené (netečkované) sloupce rovny funkcím tečkovaných sloupců, které splňují predikát FROM.

SQL:Nahraďte příkazy jejich tabulkami, AND za JOIN nebo ON nebo WHERE a vnější FOR SOME &THERE EXISTS za 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

Tabulka řádků splňujících OR dvou predikátů je UNION jejich tabulek. Pro AND NOT používáme EXCEPT (aka MINUS) (nebo idiom LEFT JOIN). FOR SOME nebo THERE EXISTS přes všechny sloupce nelze v SQL dotazovat, ale pokud chceme vědět, zda existují řádky splňující predikát, můžeme použít EXISTS kolem poddotazu s tímto predikátem.

Předpokládejme, že chceme omezit základní tabulku tak, aby každý řádek vyhovoval predikátu v některých sloupcích. Tj. PRO VŠECHNY sloupce POKUD splňují základní predikát PAK splňují predikát dotazu. Tj. PRO VŠECHNY sloupce POKUD je řádek, který tvoří, v základu, PAK je v dotazu. Požadujeme tedy v SQL, který NEEXISTUJE (VYBERTE sloupce ZE základního dotazu EXCEPT). Nebo pro každý řádek v základu požadujeme v SQL, že EXISTUJE(dotaz).

Ve standardním SQL můžete VYTVOŘIT KONTROLU ASSERTION (NEEXISTUJE (VYBRAT ID_studenta, ID_dávky FROM studentské šarže EXCEPT dotazu)) nebo ve skupině CREATE TABLE studenta můžete ZKONTROLOVAT (EXISTUJE(dotaz)). Bohužel je nepodporuje MySQL ani většina DBMS. Pokud vložíte do studentské dávky po dávce, můžete na spouštěči vyžadovat, aby EXISTUJE (dotaz). Nebo můžete přidat určité sloupce a složená omezení FK (cizí klíč).

Nyní píšeme dotaz. Chceme řádky, kde:

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)

Vypadá to jako predikát omezení s různými návratovými sloupci a přidanými řádky. SQL je stejně přímo přeloženo. Přidáme spojení se studentem, abychom získali jména studentů. Přidáme spojení pomocí student-batch, protože omezení se tím nezabývá; kontexty používající omezovací dotaz zkontrolují, zda jsou v něm podřádky student-batch (student_id, batch_id).

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

Můžete zkusit ON verzi:

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. Jak mohu uvést VŠECHNY granty, které uživatel obdržel?

  2. Co je Query Outlier a jak jej opravit

  3. Vložení mysql do java desktopové aplikace

  4. Vyberte nejběžnější hodnotu z pole v MySQL