Mysql
 sql >> база данни >  >> RDS >> Mysql

Какъв е начинът за проектиране на проста релационна база данни учител-предмет-ученик-група?

Липсва ви таблица, свързваща предмети и ученици (за точка 2):

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

Забележете, че всяка базова таблица има асоцииран шаблон на изявление за изявления за бизнес ситуацията, параметризиран от имена на колони - нейния (характерен) предикат . Редовете, които правят предиката вярно, влизат в таблицата. Забележете, че дефиницията на таблицата изглежда като стенография за предиката.

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

Тъй като изглеждате объркани от това, ще го изведа от гледна точка на това как можем да обосноваваме дизайна на таблици, ограничения и заявки. Един от начините да изразите желаното от вас ограничение изглежда е коментираната ПРОВЕРКА по-горе.

За да изразим всяка таблица, ограничение или заявка в SQL, първо решаваме нейния предикат. След това можем да преобразуваме предиката в стенография. След това можем да преобразуваме стенографията в SQL.

Предикат:

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

Използване на предикати на основната таблица:

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

Използване на съкращения:

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)

Във FROM всеки (евентуално имплицитен) псевдоним представлява таблица като даденото име на основна таблица и/или подзаявка, но с всяка колона в нейната стойност и предикат, преименувани на псевдоним .колона .

Получаваме редовете, удовлетворяващи И на два предиката, като обединим таблиците на предикатите в SQL. Ако искаме редове да отговарят на И на условие, тогава използваме ON или WHERE в SQL.

Клауза SELECT връща редове, където ЗА НЯКОИ стойности на колони с точки, върнатите (без точка) колони са равни на функции на колони с точки, които удовлетворяват предиката FROM.

SQL:Заменете изразите с техните таблици И чрез JOIN или ON или WHERE и външни FOR SOME &THERE EXISTS от 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

Таблицата от редове, удовлетворяващи ИЛИ на два предиката, е СЪЕДИНЕНИЕТО на техните таблици. За AND NOT използваме EXCEPT (известен още като MINUS) (или идиома LEFT JOIN). ЗА НЯКОИ или ТЪМ СЪЩЕСТВУВА над всички колони не могат да бъдат запитани в SQL, но ако искаме да знаем дали има редове, удовлетворяващи предикат, тогава можем да използваме EXISTS около подзаявка с този предикат.

Да предположим, че искаме да ограничим базова таблица, така че всеки ред да удовлетворява предикат на някои колони. Т.е. ЗА ВСИЧКИ колони АКО удовлетворяват основния предикат ТОГАВА те удовлетворяват предиката на заявката. Т.е. ЗА ВСИЧКИ колони АКО реда, който образуват, е в основата, ТОГАВА е в заявката. Така че ние изискваме в SQL, че НЕ СЪЩЕСТВУВА (ИЗБЕРЕТЕ колони ОТ базата ОСВЕН заявка). Или за всеки ред в базата изискваме в SQL, че СЪЩЕСТВУВА (заявка).

В стандартен SQL бихте могли да СЪЗДАВАТЕ ПРОВЕРКА НА УТВЪРДЕНИЕ (НЕ СЪЩЕСТВУВА (ИЗБЕРЕТЕ идентификатор на студент, пакет_идентификатор ОТ студент-партида ОСВЕН заявка)) или в CREATE TABLE студент-група бихте могли да ПРОВЕРИТЕ(СЪЩЕСТВУВА(заявка)). За съжаление те не се поддържат от MySQL или повечето СУБД. Ако INSERT към пакет студент след пакет, тогава можете да изисквате при задействане това EXISTS (заявка). Или можете да добавите определени колони и композитни FK (външен ключ) ограничения.

Сега пишем запитване. Искаме редове, където:

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)

Това изглежда като предикат на ограничението с различни колони за връщане и добавени редове. SQL е също толкова директно преведен. Добавяме присъединяване със студент, за да получим имена на ученици. Добавяме присъединяване с student-batch, защото ограничението не се справя с него; контекстите, използващи заявката за ограничение, проверяват дали в нея има подредове на 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

Можете да опитате ON версия:

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Подреждане по низ, който започва с номер - ActiveRecord

  2. Как да се свържете с MySQL с помощта на Node.js

  3. PDO бяха редове, засегнати по време на оператор за изпълнение

  4. Най-добрият метод за съхранение на списък с потребителски идентификатори

  5. Вземете MySQL данни в node.js (експрес) и отпечатайте с помощта на EJS