Mysql
 sql >> Database >  >> RDS >> Mysql

Schema di database per libri, autori, editori e utenti con scaffali

Avrai bisogno di un collegamento N:M tra books e authors , poiché un libro potrebbe avere più autori e ogni autore potrebbe aver scritto più di un libro. In un RDBMS ciò significa che avrai bisogno di un written_by tabella.

Il collegamento tra books e publishers tuttavia è diverso. Ogni dato libro può avere un solo editore (a meno che nel tuo sistema diverse edizioni di un libro non siano considerate lo stesso libro). Quindi tutto ciò di cui hai bisogno qui è un publisher_id chiave esterna in books

Infine, e soprattutto, stai guardando i lettori / utenti. E il loro rapporto con i libri. Naturalmente, anche questa è una relazione N:M. Spero davvero che le persone leggano più di un libro (sappiamo tutti cosa succede se ne leggi solo uno...) e sicuramente un libro viene letto da più di una persona. Ciò richiede un book_users tabella di collegamento. La vera domanda qui è:come progettarlo. Ci sono tre design di base.

  1. Tabelle separate per tipo di relazione . (come indicato da @just_somebody ) Vantaggi:hai solo INSERTS ed DELETES, mai UPDATES. Anche se questo sembra abbastanza pulito e aiuta in qualche modo con l'ottimizzazione delle query, la maggior parte delle volte non ha alcuno scopo reale se non quello di mostrare un grande grafico di database.

  2. Una tabella con uno status indicatore . (come indicato da @Hardcoded) Vantaggi:hai solo una tabella. Svantaggi:avrai INSERTS, UPDATES ed DELETES - qualcosa che RDBMS può gestire facilmente, ma che ha i suoi difetti per vari motivi (ne parleremo più avanti) Inoltre, un singolo status campo implica che un lettore può avere solo una connessione al libro in qualsiasi momento, il che significa che potrebbe essere solo nel plan_to_read , is_reading o has_read stato in qualsiasi momento e presuppone un ordine nel tempo in cui ciò accade. Se mai quella persona avesse intenzione di leggerlo di nuovo , o mettere in pausa, quindi rileggere dall'inizio ecc., una serie così semplice di indicatori di stato può facilmente fallire, perché all'improvviso quella persona is_reading ora, ma anche has_read la cosa. Per la maggior parte delle applicazioni questo è ancora un approccio ragionevole e di solito ci sono modi per progettare i campi di stato in modo che si escludano a vicenda.

  3. Un registro . INSERIRE ogni stato come una nuova riga in una tabella:la stessa combinazione di libro e lettore apparirà più di una volta. INSERIRE la prima riga con plan_to_read e un timestamp. Un altro con is_reading . Poi un altro con has_read . Vantaggi:dovrai solo INSERIRE le righe e otterrai una cronologia ordinata delle cose accadute. Svantaggi:i join tra tabelle incrociate ora devono gestire molti più dati (ed essere più complessi) rispetto agli approcci più semplici di cui sopra.

Potresti chiederti, perché c'è l'enfasi sul fatto che INSERT, UPDATE o DELETE in quale scenario? In breve, ogni volta che esegui un'istruzione UPDATE o DELETE è molto probabile che di fatto perda dati. A quel punto devi fermarti nel tuo processo di progettazione e pensare "Cosa sto perdendo qui?" In questo caso, si perde l'ordine cronologico degli eventi. Se ciò che gli utenti stanno facendo con i loro libri è al centro della tua applicazione, potresti voler raccogliere più dati che puoi. Anche se in questo momento non importa, questo è il tipo di dati che potrebbero permetterti di fare "magie" in seguito. Potresti scoprire quanto velocemente qualcuno sta leggendo, quanti tentativi ha bisogno per finire un libro, ecc. Tutto questo senza chiedere all'utente alcun input aggiuntivo.

Quindi, la mia risposta finale è in realtà una domanda:

Modifica

Dal momento che potrebbe non essere chiaro come sarebbe un registro e come funzionerebbe, ecco un esempio di tale tabella:

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

Ora, invece di aggiornare la tabella "user_read" nel tuo schema progettato ogni volta che lo stato di un libro cambia, ora INSERISCI gli stessi dati nel registro che ora riempie una cronologia di informazioni:

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

Quando quella persona inizia effettivamente a leggere, fai un altro inserto:

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

e così via. Ora hai un database di "eventi" e poiché la colonna timestamp si riempie automaticamente, ora puoi dire cosa è successo quando. Si noti che questo sistema non garantisce che esista un solo 'is_reading' per una specifica coppia di libri utente. Qualcuno potrebbe smettere di leggere e poi continuare. I tuoi join dovranno tenerne conto.