2009-07-23 18 views
3

Wie können Sie eine Beziehung null, eine oder viele Typen modellieren, ohne die erste Normalform zu unterbrechen? Das heißt, keine NULL-Werte speichern.So modellieren Sie eine optionale 1: n-Beziehung in 1NF

Getrennte Beziehungstabelle? Ist es "wert", eine Tabelle hinzuzufügen, oder ist dies eine Über-Normalisierung?

Hier ist ein Beispiel, das zu meiner realen Welt Fall entspricht:

Sagen wir ein College haben, mit einigen freien Kursen und einigen freien Schlafsäle. Einige der Kurse und Schlafsäle sind jedoch mit einer Gebühr verbunden. Und viele der Kurse und Zimmer haben die gleiche Gebühr (Betrag), obwohl sie verschiedene Kurse/Zimmer sind.

wir So haben:

tblCourse 
Id 
Name 

tblDormRoom 
Id 
Address 

tblFee 
Id 
Amount 

Um dieses mein nehmen zu modellieren war zwei Tabellen hinzufügen, um die optional eine Eins-zu-viele-Beziehung zu halten.

tblCourseToFee 
CourseId 
FeeId 

tblDormRoomToFee 
DormRoomId 
FeeId 

So kann ich keine Nullwert zu speichern vermeiden kann, und auch doppelte Speicherung der Fee vermeiden, die zwischen Dormroom und Kurs geteilt werden.

Und die schnelle n dreckige Version betrachtet, die nicht streng an 1NF anhaftet:

tblFee 
Id 
CourseId (nullable) 
DormRoomId (nullable) 
Amount 

Dies nur eine Tabelle anstelle von drei verwendet, aber NULL-Werten führt ..

Antwort

2

Dies ist ein Interessante Frage - ein gutes Beispiel für eine Eins-zu-Viele-Beziehung in der ersten Normalform findet sich on Wikipedia (Ich möchte hier einige Inhalte posten, aber es ist nicht Stackoverflow-Format-freundlich).

Die Grundidee ist, dass Sie zwei Tabellen und die Kennung der Haupttabelle definieren wird als Kennung der zugehörigen Tabelle mit dem Verständnis verwendet, dass die dazugehörige Tabelle doppelte Kennungen enthält.

Arbeiten Sie aus Neugierde an einem Datamining-Projekt? Ich wäre daran interessiert, mehr darüber zu erfahren, wie dies angewendet wird.

1

sehen Andrew Link zu Wikipedia, und beachten Sie, dass die ‚keine NULL-Werte in 1NF‘ Mahnung von Datum controverisal ist bestenfalls - nicht häufig unpraktisch zu erwähnen. Wenn Nullen gut genug für Codd sind, sind sie gut genug für mich ;-) das sagte, der normale (Wortspiel beabsichtigt) Weg, eine Null, eine oder viele Beziehung zu modellieren ist mit einer Kind-Tabelle, z.

create table Parent (
    Id int not null identity(1), 
    Somefield nvarchar(256) not null, 
    ... 
) 

create table Child (
    Id int not null identity(1), 
    ParentId int not null, --foreign key to Parent table's Id 
    AnotherField nvarchar(128) not null 
    ... 
) 
+0

Was ist, wenn Sie eine zweite Parent2-Tabelle mit der gleichen optionalen Eins-zu-viele-Beziehung zur Tabelle Child haben? (Das wäre äquivalent zu meinem Fall) – jandersson

+0

dann haben Sie eine bedingte Beziehung, die in relationalen Datenbanken nicht wirklich gut behandelt wird. Eine Lösung sind zwei sich gegenseitig ausschließende Elternfelder, die sich gegenseitig ausschließen lassen. Eine andere Lösung sind zwei verschiedene Child-Tabellen, dito. Eine andere Lösung ist ein Feld, um Ihnen den Typ/Zustand zu sagen. Wenn eine untergeordnete Zeile zu beiden Eltern gehören kann, kann eine Brückentabelle sinnvoller sein. Ich würde vorschlagen, dass Sie zuerst die Semantik Ihres Entitätsmodells posten, da dies eine verdächtige Struktur ist ... –

+0

@jandersson - In diesem Fall würden Sie eine zweite Fremdschlüsselbeziehung von Parent2 zu Child erstellen, indem Sie ein Parent2Id-Feld hinzufügen die Child-Tabelle. Steven's Ansatz ist klassisch 3NF und sollte für 99% aller Situationen verwendet werden. Der einzige Sinn des 1NF besteht darin, statische Datensätze für schnelle Lesevorgänge zu optimieren. –

0

Schauen Sie sich dieses Problem semantisch an. Ist es eine ternäre Beziehung oder zwei binäre Beziehungen? In einfachen Worten: Ist die Gebühr gesammelt

  • für einen Kurs
  • für ein Wohnheim
  • für ein Wohnheim verwendet in bleiben, während einen Kurs

    Für die ersten beiden Fälle besuchen Sie müssen die zwei untergeordneten Tabellen haben. Wenn Fall drei wahr ist, müssen Sie nur eine Schnittmenge zwischen Kurs, Gebühr und Wohnheim haben. Oft ist das Vorhandensein oder Fehlen von NULLs sehr eng mit subtilen Designproblemen verbunden.
+0

Zwei binäre Beziehungen, dh ein Student darf entweder nur ein Zimmer mieten, nur ein nehmen Natürlich oder beides. Ich kann sehen, wie zwei untergeordnete Tabellen funktionieren würden, obwohl das den Nachteil der redundanten Speicherung der Gebührendaten hätte, für die Fälle, in denen ein Raum zufällig die gleiche Menge wie ein Kurs hat. Haben Sie Anmerkungen zu der Lösung, zwei Bridge-Tabellen zu verwenden und die Gebühr als separate Einheit zu speichern? – jandersson

+0

Student (id, name)
Kurs (Kurs #, Name)
Wohnheim (Wohnheim #, Name)
Eingang (Eingang #, Menge, payment_mode, date_of_payment)
dorm_receipt (Wohnheim #, Empfang #)
course_receipt (Kursnummer, Quittungsnummer)
Durch Verschieben der Gebührenbezahlungsinformationen in eine separate Tabelle können Sie Inkonsistenzen in den oben genannten Fällen vermeiden. Dies gilt auch für den Fall, dass ein Schüler eine einmalige Zahlung für den Wohnheim und den Kurs leistet. – bkm

+0

Ich möchte mein früheres Design überarbeiten. Das aktuelle Design kann nur zwei Arten von Zahlungen verarbeiten - der Student zahlt für einen Wohnheim oder der Student zahlt für einen Kurs oder beides. Möglicherweise haben Sie in Zukunft weitere Szenarien. Sie könnten nur eine Tabelle für alle Zahlungen wie zuvor haben: Empfang (Quittung #, Betrag, Zahlungsmodus, Datum) Student_Payment (student_id, payment_code) Zahlungscode kann Werte wie 'Wohnheim', 'Kurs', 'Prüfung' etc ... Die Tatsache, dass ein Student sich für einen Kurs eingeschrieben hat, unterscheidet sich von der Tatsache, dass er/sie dafür bezahlt hat und unabhängig modelliert werden kann – bkm

Verwandte Themen