Spiegando 2NF vs 3NF con un esempio


13

Ho un problema con il secondo modulo normale (2NF) e non sono stato in grado di risolverlo utilizzando Google. Mi sta facendo impazzire perché sono un insegnante e non voglio insegnare cose sbagliate ai miei studenti.

Diamo una tabella con 5 campi.

Gradings = {StudentName, SubjectCode, SubjectName, #Exam, Grade}

Le dipendenze sono in questo modo:

StudentName, SubjectCode, #Exam -> Grade

SubjectCode -> SubjectName

SubjectName -> SubjectCode

Pertanto, la chiave candidata 1 è {StudentName, SubjectCode, #Exam} e la chiave candidata 2 è {StudentName, SubjectName, #Exam} .

Gli attributi primi sono {StudentName, SubjectCode, SubjectName, #Exam} e gli attributi non primi sono Grade

Secondo la definizione di seconda forma normale, un attributo non primo non può dipendere da una parte di una chiave candidata. L'unico attributo non primo (Grado) non dipende da una parte di una chiave candidata, quindi questa tabella sembra in 2NF.

Il problema è che penso che qualcosa non vada (e potrei sbagliarmi). Penso che i soggetti dovrebbero avere il proprio tavolo.

Gradings = {StudentName, Subject Code, #Exam, Grade}

Subject = {Subject Code, SubjectName}

Ma 2NF non produce questo. 3NF riguarda le dipendenze tra attributi non primi quindi non produce neanche questo. Ma mi sembra che questo sia il risultato giusto, perché non ha ridondanza.

Immagino che se l'attributo non primo fosse definito come "attributo che non è una chiave candidata", 2NF produrrebbe il risultato desiderato. Ma l'ho verificato più volte e l'attributo non primo è definito come "attributo che NON APPARTIENE a una chiave candidata".

Che cosa sto facendo di sbagliato?

Risposte:


9

La tua relazione è in 3NF, (e non solo in 2NF), dal momento che come dici l'unico attributo non primo è Grado , che appare solo sul lato destro dei tuoi FD.

La relazione non è in BCNF, perché il lato sinistro dei due piccoli FD non è un superkey.

Tuttavia, è possibile decomporre senza perdita la relazione tra ( SubjectCode , SubjectName ) e ( StudentName, SubjectCode, #Exam, Grade ) o ( StudentName, SubjectName, #Exam, Grade )

Questa decomposizione offre due relazioni BCNF e preserva tutte le dipendenze funzionali. Questo non è sempre possibile (puoi sempre scomporre una relazione con 3NF, ma non necessariamente con BCNF).

2NF

Se si desidera un esempio di 2NF (e non 3NF), la relazione deve contenere dipendenze transitive.

Ad esempio, supponiamo di avere una colonna Punteggio. Punteggio intuitivo-> Grado poiché tutti gli esami con lo stesso punteggio dovrebbero ottenere lo stesso voto (altrimenti sarebbe piuttosto ingiusto), ma nota che non possiamo dire Punteggio-> Punteggio poiché diversi punteggi possono avere lo stesso voto (11% e 12% sarebbe probabilmente "Fail", per esempio).

Ora la tua relazione è:

Classificazioni ( StudentName, SubjectCode, SubjectName, #Exam, Score, Grade )

e hai una nuova forma di ridondanza poiché ogni volta che inserisci un risultato con lo stesso punteggio di un altro record di classificazione devi ripetere anche il voto corrispondente. Per arrivare a 3NF è quindi possibile scomporre

ScoreGrades ( Punteggio, Grado )

con Punteggio come chiave e

Punteggi ( StudentName, SubjectCode, SubjectName, #Exam, Score )


4

Hai ragione in tutto ciò che dici. Subject Code, SubjectName deve andare nella propria tabella per applicare le dipendenze desiderate. Questo è un buon esempio del motivo per cui 2NF e 3NF non sono sufficienti per produrre buoni progetti di database - è invece necessario Boyce Codd Normal Form (BCNF).

2NF e 3NF sono sostituiti da BCNF che praticamente parlando rende obsoleti quei NF minori *. BCNF è il più importante e probabilmente più semplice da spiegare e applicare. Come insegnante ti suggerisco di dedicare più tempo a BCNF e meno a 2NF e 3NF. Se una tabella soddisfa i requisiti di BCNF, allora soddisfa anche 2NF e 3NF.


* 3NF non è la forma normale che preserva la massima dipendenza. La forma normale chiave elementare (EKNF) è. A rigor di termini è EKNF, non BCNF, che rende obsoleto 3NF, ma EKNF viene ingiustamente trascurato e la maggior parte dei libri di testo e dei corsi non lo menziona nemmeno. Ciò che equivale alla stessa cosa è progettare in BCNF e quindi verificare che tutte le dipendenze desiderate e tutte le altre regole di integrità possano essere correttamente applicate - in caso contrario, modificare il progetto. Nessuno degli NF è una soluzione completa per l'integrità dei dati, ma BCNF è generalmente il più vicino ed è il più semplice da spiegare e utilizzare.


Hai qualche buona referenza per EKNF, specialmente per un principiante? Sto cercando di leggerlo e trovare una buona documentazione per questo si è rivelato difficile. Al di fuori del riassunto di una riga di Wiki, una spiegazione funzionale funzionante delle sottigliezze di EKNF vs BCNF / 3NF non ho ancora incontrato.
Saijin_Naib il

2

Non dirò quanto tempo è passato da quando ho imparato tutto questo. Ma ricordo di avere un prof che, dopo averci insegnato diligentemente il significato corretto di "dipendenza funzionale" e "attributo non primo" e tutte le altre parole d'ordine, ci ha fatto una serie di semplici domande da porre per vedere se un particolare normale la forma è stata raggiunta. Vediamo se riesco a ricordare così lontano ...

Abbiamo identificato la / le chiave / i candidata / e, quindi facciamo questa domanda sugli altri attributi non primi. In questo caso, ce n'è solo uno: voto.

Quali sono le informazioni minime assolute di cui abbiamo bisogno per identificare in modo univoco il voto? Dobbiamo conoscere lo studente, la materia e l'esame sostenuti. Bene, questa è una delle chiavi candidate.

EDIT: VVV

Ma la risposta potrebbe anche essere stata il nome dello studente, il nome della materia e l'esame. Ciò corrisponderebbe alla seconda chiave candidata.

Supponendo che SubjectCode e SubjectName siano entrambi chiavi candidate per l'entità Subject, non vi è motivo di avere entrambi questi campi qui. Un riferimento univoco a una riga nella tabella Soggetti è abbastanza. Quindi potremmo liberarci del tutto dal campo SubjectName senza sacrificare l'integrità del modello.

Tuttavia, nella mia risposta originale, nel mio desiderio di mostrare un altro livello di normalizzazione, ho ignorato che SubjectName era stato usato in una chiave candidata e lo consideravo solo un altro attributo non primo. Immagino fosse così ovvio che questo fosse un campo inutile, pensavo che sarebbe stato altrettanto ovvio per tutti e dato che in entrambi i casi ci siamo sbarazzati del campo, che importanza aveva?

Ma invece di rimuovere quella parte della risposta, la terrò per il confronto.

MODIFICA FINE: ^ ^ ^

Quali sono le informazioni minime assolute di cui abbiamo bisogno per identificare in modo univoco il nome del soggetto?

SubjectName dipende solo da SubjectCode, un sottoinsieme della chiave candidata. Quindi questa tupla non è in 2nf. SubjectCode dovrebbe essere la chiave primaria di una tabella Subject in modo che sia la posizione corretta per posizionare SubjectName. Rimuovilo da questa tupla ed è ora in 2nf.

Se poniamo la domanda di un attributo e la risposta non è tutta o parte della chiave candidata, allora la tupla non è in 3nf. Ma questa tupla è anche banalmente in 3a e oltre, poiché abbiamo finito i campi per porre domande. ;)

Nota: quando diciamo "normalizzare", ci riferiamo a un processo che viene applicato a un'entità logica. Dato che la tupla fornita sembra essere la definizione di un'entità chiamata "grade", allora possiamo normalizzarla. Tuttavia, ad un certo punto ho detto "questa tupla non è in 2nf", cosa che avrebbe dovuto essere più propriamente ", questa entità non è in 2nf". Mi scuso se questo ha causato confusione.


2

L'unico attributo non primo (Grado) non dipende da una parte di una chiave candidata, quindi questa tabella sembra in 2NF.

È in 2NF.

Il problema è che penso che qualcosa non vada (e potrei sbagliarmi). Penso che i soggetti dovrebbero avere il proprio tavolo.

Non c'è motivo di aspettarsi che i soggetti debbano avere la propria tabella per una decomposizione della tabella originale a 2NF . Stai confondendo una vaga nozione di "dovrebbe" con ciò che una particolare forma normale ti dà effettivamente.

3NF riguarda le dipendenze tra attributi non primi quindi non produce neanche questo.

"3NF riguarda le dipendenze tra attributi non primi" non è una definizione corretta di 3NF, quindi "quindi non produce neanche questo" non è una conclusione valida. Sebbene l'applicazione di una definizione effettiva mostri che la tabella è in 3NF, senza la tabella degli studenti necessaria. Ma ancora una volta, non c'è motivo di aspettarsi che ci sarebbe.

Ma mi sembra che questo sia il risultato giusto, perché non ha ridondanza.

Ancora una volta, la "ridondanza" è inutilmente vaga, quindi le aspettative sul "perché" e sul tavolo degli studenti sono prive di fondamento. Diverse forme normali sono prive di e soggette a particolari tipi di anomalie e "ridondanza" associata. Ma può rimanere altra "ridondanza" non affrontata dalla normalizzazione.

Questa tabella non è in BCNF, dal momento che ha FD che non sono CK. La sua scomposizione in base al BCNF porta al tavolo degli studenti. BCNF è la forma normale più alta per gestire i JD (join dipendenze) che accompagnano gli FD. Tuttavia, altri JD possono essere problematici (cioè non "implicati dai CK") e dovrebbero essere rimossi mediante normalizzazione a 5NF.

PS La tabella originale soddisfa anche il FD {StudentName, SubjectName, #Exam} -> Grade.

Le dipendenze sono in questo modo:

Cosa dovrebbe significare questo? Non è chiaro.

Intendi "Questi sono tutti i FD non banali che detengono"? No, perché implicano il quarto. "Qui ci sono alcuni FD che detengono"? No, ciò significa che gli FD nella chiusura transitiva restano validi, ma ciò non significa che altri non lo siano , ma tu sei stato in grado di determinare i CK. "I FD che detengono sono esattamente quelli nella chiusura transitiva di questi"? Se intendessi ciò, lo sapresti solo se lo avessi mostrato , cioè avresti dovuto trovare quella chiusura (in genere, tramite una copertura minima / canonica) e quindi aver dimostrato che non ci sono altri FD; hai fatto? Indipendentemente da ciò, ciò che hai scritto non significa che. Quindi mi aspetto che tu non stia ragionando profondamente sulla situazione di FD e CK.


0

Hai ragione, i soggetti richiedono una propria tabella. Se scegli una delle tue chiavi candidate, subject_codeo subject_namediventa una chiave candidata non primaria. Quindi rimuovere il campo delle materie non primarie dalla tabella delle classifiche.

Hai una dipendenza funzionale sull'argomento per il quale hai due identificatori univoci. Ciò è dimostrato dalla dipendenza transitiva tra subject_codee subject_name. Ciò indica un requisito per creare una tabella contenente quei due campi e rimuovere uno di questi campi da tutte le altre tabelle. Questa tabella potrebbe avere colonne dipendenti aggiuntive, anche se non ne vedo nessuna in questo esempio. In 3a forma normale hai selezionato.

il voto dipende dagli altri tre campi (chiave candidata) nella nuova tabella dei voti. Come notato sopra, è necessario selezionare uno dei campi candidati per la tabella degli argomenti. Normalmente questo sarebbe un valore di codice se disponibile in quanto tendono ad essere più stabili. Il modello risultante è in 3nf poiché tutti i campi non chiave sono completamente dipendenti dai campi nella chiave primaria.

Un'ulteriore analisi del problema (requisiti) probabilmente produrrà una tabella delle sessioni rispetto alla quale vengono applicati i segni. È improbabile che l'attuale modello copra uno studente che ripete un corso. Questo verrebbe trattato in una lezione successiva.

È probabile che anche gli studenti diventino una tabella separata in quanto è possibile avere più studenti con lo stesso nome. Ciò sarebbe probabilmente risolto con l'aggiunta di una chiave primaria sintetica (numero studente?).

subjects --->  sessions ---+--> grades
students  -----------------+

3
"Se scegli una delle tue chiavi candidate , o subject_code o subject_name diventa una chiave candidata non primaria ." Questo è chiaramente sbagliato. Il resto dell'analisi ha alcuni punti preziosi ma quando si parte da un punto falso, non possiamo fare affidamento sulle conclusioni.
ypercubeᵀᴹ

-7

Mi sto preparando ad eliminare questo dato che è considerato errato

Il nome del soggetto è anche un attributo non primo e dipende da una parte della chiave primaria Codice soggetto (infrange la regola - non deve esserci alcuna dipendenza parziale di alcuna colonna dalla chiave primaria).

Ciò è vietato nella seconda forma normale e dovrebbe pertanto essere inserito nella propria tabella come si sospettava.

Penso che il punto in cui ti sei sbloccato sia l'identificazione di due set di chiavi candidate, quando crei la tabella devi scegliere un set di chiavi candidate per creare la chiave primaria. Le colonne rimanenti diventano attributi non primi, ad esempio, se si sceglie la seconda chiave candidata, il Codice soggetto diventa un attributo non primo dipendente dalla parte della chiave primaria (Nome soggetto) e deve essere inserito nella propria tabella.

È importante insegnare la 1a, la 2a e la 3a forma normale in modo che si costruiscano l'una sull'altra. BCNF è anche essenzialmente un'estensione alla terza forma normale, quindi è essenziale una forte comprensione dei livelli inferiori.

Ulteriore; uno sviluppatore esperto non prenderà in considerazione i livelli indipendenti di normalizzazione perché molte regole diventano intuitive.

Sapranno anche quando infrangere le regole di normalizzazione per risolvere alcuni problemi di progettazione e ottimizzazione. La normalizzazione dovrebbe essere trattata come una guida per una buona progettazione, non una regola rigorosa, credo che sarebbe anche un buon punto di insegnamento.


1
L'OP afferma correttamente che "è la chiave candidata 2. {StudentName, SubjectName, #Exam}" Quindi, StudentNameè un attributo primo.
ypercubeᵀᴹ

1
"quando crei la tabella devi scegliere un set di chiavi candidate per creare la chiave primaria. Le colonne rimanenti diventano attributi non primi. " Questo è chiaramente sbagliato.
ypercubeᵀᴹ
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.