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

Схема на база данни за книги, автори, издатели и потребители с рафтове за книги

Ще ви трябва N:M връзка между books и authors , тъй като една книга може да има няколко автора и всеки автор може да е написал повече от една книга. В RDBMS това означава, че ще ви трябва written_by таблица.

Връзката между books и publishers обаче е различно. Всяка дадена книга може да има само един издател (освен ако във вашата система различни издания на книга се считат за една и съща книга). Така че всичко, от което се нуждаете тук, е publisher_id външен ключ в books

И накрая, и най-важното, вие гледате към читателите/потребителите. И връзката им с книгите. Естествено, това също е връзка N:M. Сигурно се надявам, че хората четат повече от една книга (всички знаем какво се случва, ако някога прочетете само една...) и със сигурност една книга се чете от повече от един човек. Това изисква book_users свързваща маса. Истинският въпрос тук е как да го проектираме. Има три основни дизайна.

  1. Разделете таблиците по тип връзка . (както е посочено от @just_somebody ) Предимства:Имате само INSERTS и DELETES, никога UPDATES. Въпреки че това изглежда някак спретнато и донякъде помага при оптимизирането на заявките, през повечето време няма действителна цел, освен показване на голяма диаграма на базата данни.

  2. Една таблица със status индикатора . (както е посочено от @Hardcoded) Предимства:Имате само една маса. Недостатъци:Ще имате INSERTS, UPDATES и DELETES - нещо, което RDBMS може лесно да се справи, но което има своите недостатъци по различни причини (повече за това по-късно) Също така, един status полето означава, че един читател може да има само една връзка с книгата по всяко време, което означава, че може да бъде само в plan_to_read , is_reading или has_read състояние във всеки момент от време и предполага ред във времето, когато това се случва. Ако този човек някога би планирал да го прочете отново , или пауза, след което отново прочетете отначало и т.н., такава проста серия от индикатори за състояние може лесно да се провали, защото изведнъж този човек is_reading сега, но също и has_read нещото. За повечето приложения това все още е разумен подход и обикновено има начини за проектиране на полета за състояние, така че да се изключват взаимно.

  3. Дневник . ВМЕСВАТЕ всеки статус като нов ред в таблица - една и съща комбинация от книга и четец ще се появи повече от веднъж. ВМЕСВАТЕ първия ред с plan_to_read , и времева марка. Друг с is_reading . След това още един с has_read . Предимства:Винаги ще трябва да ВМЕСВАТЕ редове и ще получите чиста хронология на нещата, които са се случили. Недостатъци:Съединенията на кръстосани таблици вече трябва да се справят с много повече данни (и да са по-сложни), отколкото в по-простите подходи по-горе.

Може да се запитате защо се набляга на това дали ВМЕСВАТЕ, АКТУАЛИЗИРАТЕ или ИЗТРИВАТЕ в какъв сценарий? Накратко, когато стартирате оператор UPDATE или DELETE, е много вероятно да загубите данни. В този момент трябва да спрете в процеса на проектиране и да помислите „Какво губя тук?“ В този случай губите хронологичния ред на събитията. Ако това, което потребителите правят със своите книги, е в центъра на вашето приложение, може да искате да съберете колкото се може повече данни. Дори ако в момента няма значение, това е типът данни, който може да ви позволи да правите „магия“ по-късно. Можете да разберете колко бързо някой чете, колко опита му трябва, за да завърши книга и т.н. Всичко това, без да питате потребителя за допълнителен вход.

И така, окончателният ми отговор всъщност е въпрос:

Редактиране

Тъй като може да не е ясно как би изглеждал дневникът и как ще функционира, ето пример за такава таблица:

CREATE TABLE users_reading_log (
  user_id INT,
  book_id INT,
  status ENUM('plans_to_read', 'is_reading', 'has_read'),
  ts TIMESTAMP DEFAULT NOW()
)

Сега, вместо да актуализирате таблицата "user_read" във вашата проектирана схема всеки път, когато състоянието на книга се промени, сега ВМЕСВАТЕ същите тези данни в дневника, който сега се изпълва с хронология на информацията:

INSERT INTO users_reading_log SET 
  user_id=1,
  book_id=1,
  status='plans_to_read';

Когато този човек действително започне да чете, правите друго вмъкване:

INSERT INTO users_reading_log SET 
  user_id=1,
  book_id=1,
  status='is_reading';

и така нататък. Сега имате база данни със „събития“ и тъй като колоната с времеви печат се запълва автоматично, вече можете да кажете какво се е случило кога. Моля, имайте предвид, че тази система не гарантира, че съществува само едно 'is_reading' за конкретна двойка потребител-книга. Някой може да спре да чете и по-късно да продължи. Вашите присъединявания ще трябва да отчитат това.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Показване на произволен резултат на mysql

  2. HTML полето за въвеждане не попълва PHP стойност след първото интервал

  3. Как да обедините две таблици в MySQL

  4. Сума стойностите на многомерния масив по ключ без цикъл

  5. Как мога да избера съседен ред в sql, когато съм подреден от друго поле?