SQL-Problem 2. Normalform



  • In meiner Adressenverwaltung sind die Felder PLZ und Wohnort enthalten. Wie kann ich die Redundanzen, die zwangsläufig in den Wohnorten eingegegeben werden (z.B. "München", aber verschiedene Postleitzahlen), vermeiden?

    Und ist es sinnvoll, auch die Redundanzen, die im Feld "Strasse" enthalten sein können (z.B. "Hauptstraße" in verschiedenen Städten) zu behandeln?

    Bin für jede Hilfe dankbar.



  • über lookup-tabellen. das heißt, du erstellst z.b. für orte eine tabelle "orte".

    Or_ID int (PK)
    Or_Ort varchar(200)

    und in der haupttabelle, in welcher der ort vorkommt, schreibst du statt des ortnamens die id deiner tabelle "orte", also Or_ID rein (das feld wird in der haupttabelle dann auch ein int). so hast du im falle mehrerer gleicher orte in der haupttabelle nur immer die gleiche zahl stehen anstantt längerer strings.

    nachteil: das abfragen wird komplizierter (nicht langsamer), da du joinen musst.

    dasselbe kannst du mit allen anderen textfeldern machen, die mehrfach vorkommen können. ob das dann alles sinnvoll ist, steht auf einem anderen blatt.



  • Das hilft mir erstmal weiter. Danke schön.

    tenim schrieb:

    über lookup-tabellen. das heißt, du erstellst z.b. für orte eine tabelle "orte".

    Or_ID int (PK)
    Or_Ort varchar(200)

    und in der haupttabelle, in welcher der ort vorkommt, schreibst du statt des ortnamens die id deiner tabelle "orte", also Or_ID rein (das feld wird in der haupttabelle dann auch ein int). so hast du im falle mehrerer gleicher orte in der haupttabelle nur immer die gleiche zahl stehen anstantt längerer strings.

    nachteil: das abfragen wird komplizierter (nicht langsamer), da du joinen musst.

    dasselbe kannst du mit allen anderen textfeldern machen, die mehrfach vorkommen können. ob das dann alles sinnvoll ist, steht auf einem anderen blatt.



  • Martin22 schrieb:

    In meiner Adressenverwaltung sind die Felder PLZ und Wohnort enthalten. Wie kann ich die Redundanzen, die zwangsläufig in den Wohnorten eingegegeben werden (z.B. "München", aber verschiedene Postleitzahlen), vermeiden?

    Naja du kannst Tabellen dafür machen. Du solltest aber nicht unbedingt. Und ... was hat das mit der 2NF zu tun? Antwort: erstmal nämlich gar nix.

    Ein Stringfeld wo mehrfach das selbe drinnen steht ist nicht gleich ne Entity.
    Oder willst du dann auch Tabellen für Vornamen, Nachnamen etc. anlegen, nur weil da öfter das selbe eingegeben wird?

    Martin22 schrieb:

    Und ist es sinnvoll, auch die Redundanzen, die im Feld "Strasse" enthalten sein können (z.B. "Hauptstraße" in verschiedenen Städten) zu behandeln?

    Nein, ist normalerweise nicht sinnvoll. In den meisten Anwendungen wäre es sogar eine ziemlich schlechte Idee.

    ps: Ein paar Anmerkungen/Erklärungen dazu...

    * Der Strassenname alleine ist keine Entity. "Hauptstrasse" ist bloss ein String, kein sinnvolles "Objekt". Denn was "Hauptstrasse" bedeutet ist z.B. davon abhängig in welchem Ort sich diese "Hauptstrasse" befindet.

    * Auch der Strassenname + Ortsname ist noch nicht eindeutig. z.B. gibt es in Österreich ein "Eggersdorf" und in Deutschland ebenfalls. Beide werden vermutlich eine "Hauptstrasse" haben. "Eggersdorf, Hauptstrasse" ist also auch kein sinnvolles Objekt.

    * Du kannst auch identische Werte bei Land, Ort und Strassenname haben, und dennoch unterschiedliche Postleitzahlen - bei langen Strassen kann das schonmal vorkommen.

    * Je nach Land wird es auch möglich sein dass du die selbe Postleitzahl hast, aber unterschiedliche Ortsnamen.

    * Um den Strassennamen in eine eigene Tabelle auszulagern müsste man Strassenname + Hausnummer aufsplitten. Das geht in vielen Ländern, aber es würde mich nicht wundern wenn du in anderen Ländern damit Probleme bekommst.

    Alles in allem ist es kaum möglich Adressen irgendwie sinnvoll in kleinere Teile zu zerpflücken. Üblich ist eher dass man eine Adressen Tabelle macht, die z.B. aus folgenden Feldern besteht
    - Name
    - Adresse 1
    - Adresse 2
    - Ort
    - Bundesland
    - Postleitzahl
    - Land

    "Name" ist dabei wirklich nur EIN Feld. Eine Auftrennung in kleinere Teile (z.B. Vorname, Nachname) ist riskant, und so lange man nicht explizit Personen verwalten will sondern eben Adressen, zahlt es sich nicht aus hier weiter zu unterteilen. Weil es eben auch alles andere als einfach ist, wenn man internationale Adressen und Namensschema erlauben möchte, ohne seine Kunden zu zwingen ihren Namen irgendwie zu "verunstalten".

    In "Adresse 1" und "Adresse 2" kommt dabei das rein was auch immer in dem Land üblich ist. Bei uns als z.B. Strassenname und Hausnummer beide in "Adresse 1", und "Adresse 2" bleibt leer. Bzw. manchmal ist "Adresse 2" auch der Name einer Siedlung o.ä. In anderen Ländern ist "Adresse 2" allerdings für jede bzw. fast jede Adresse nötig. (Und in wieder anderen kann es sein dass sogar 2 Zeilen noch zu wenig sind - hier 3 oder 4 vorzusehen wäre also vermutlich auch nicht total bekloppt.)

    "Ort" ist mehr oder weniger klar.

    Der Name "Bundesland" ist vielleicht nicht optimal, denn je nach Land kommt hier auch der Name einer Provinz, Region, eines Kanton o.ä. rein. Ist zwar alles recht ähnlich, aber nicht 100% identisch mit dem Konzept "Bundesland".

    "Postleitzahl" und "Land" sind auch mehr oder weniger klar.

    Und ganz wichtig dass alles ausreichend lange String Felder sind. Eine Postleitzahl ist halt nicht unbedingt eine Zahl, genau so wie eine Seriennummer nicht unbedingt eine Nummer ist.



  • Im alten Adressenverzeichnis finden sich vielfach Einträge wie Tübingen, tübingen, Tuebingen und sogar Thübingen, die Daten sind somit nicht konsistent. Solche fehlerträchtigen Redundanzen würde ich künftig gern vermeiden und bei der Gelegenheit ordentlich Speicher sparen.

    Deine Empfehlung, Vorname und Nachname oder gar Strassenname und Hausnummer zusammenzufassen sind aber klare Verstöße gegen die Normalisierungsregeln (vergl. Satz von Delobel) und deshalb völlig unbrauchbar.

    hustbaer schrieb:

    Martin22 schrieb:

    In meiner Adressenverwaltung sind die Felder PLZ und Wohnort enthalten. Wie kann ich die Redundanzen, die zwangsläufig in den Wohnorten eingegegeben werden (z.B. "München", aber verschiedene Postleitzahlen), vermeiden?

    Naja du kannst Tabellen dafür machen. Du solltest aber nicht unbedingt. Und ... was hat das mit der 2NF zu tun? Antwort: erstmal nämlich gar nix.

    Ein Stringfeld wo mehrfach das selbe drinnen steht ist nicht gleich ne Entity.
    Oder willst du dann auch Tabellen für Vornamen, Nachnamen etc. anlegen, nur weil da öfter das selbe eingegeben wird?

    Martin22 schrieb:

    Und ist es sinnvoll, auch die Redundanzen, die im Feld "Strasse" enthalten sein können (z.B. "Hauptstraße" in verschiedenen Städten) zu behandeln?

    Nein, ist normalerweise nicht sinnvoll. In den meisten Anwendungen wäre es sogar eine ziemlich schlechte Idee.

    ps: Ein paar Anmerkungen/Erklärungen dazu...

    * Der Strassenname alleine ist keine Entity. "Hauptstrasse" ist bloss ein String, kein sinnvolles "Objekt". Denn was "Hauptstrasse" bedeutet ist z.B. davon abhängig in welchem Ort sich diese "Hauptstrasse" befindet.

    * Auch der Strassenname + Ortsname ist noch nicht eindeutig. z.B. gibt es in Österreich ein "Eggersdorf" und in Deutschland ebenfalls. Beide werden vermutlich eine "Hauptstrasse" haben. "Eggersdorf, Hauptstrasse" ist also auch kein sinnvolles Objekt.

    * Du kannst auch identische Werte bei Land, Ort und Strassenname haben, und dennoch unterschiedliche Postleitzahlen - bei langen Strassen kann das schonmal vorkommen.

    * Je nach Land wird es auch möglich sein dass du die selbe Postleitzahl hast, aber unterschiedliche Ortsnamen.

    * Um den Strassennamen in eine eigene Tabelle auszulagern müsste man Strassenname + Hausnummer aufsplitten. Das geht in vielen Ländern, aber es würde mich nicht wundern wenn du in anderen Ländern damit Probleme bekommst.

    Alles in allem ist es kaum möglich Adressen irgendwie sinnvoll in kleinere Teile zu zerpflücken. Üblich ist eher dass man eine Adressen Tabelle macht, die z.B. aus folgenden Feldern besteht
    - Name
    - Adresse 1
    - Adresse 2
    - Ort
    - Bundesland
    - Postleitzahl
    - Land

    "Name" ist dabei wirklich nur EIN Feld. Eine Auftrennung in kleinere Teile (z.B. Vorname, Nachname) ist riskant, und so lange man nicht explizit Personen verwalten will sondern eben Adressen, zahlt es sich nicht aus hier weiter zu unterteilen. Weil es eben auch alles andere als einfach ist, wenn man internationale Adressen und Namensschema erlauben möchte, ohne seine Kunden zu zwingen ihren Namen irgendwie zu "verunstalten".

    In "Adresse 1" und "Adresse 2" kommt dabei das rein was auch immer in dem Land üblich ist. Bei uns als z.B. Strassenname und Hausnummer beide in "Adresse 1", und "Adresse 2" bleibt leer. Bzw. manchmal ist "Adresse 2" auch der Name einer Siedlung o.ä. In anderen Ländern ist "Adresse 2" allerdings für jede bzw. fast jede Adresse nötig. (Und in wieder anderen kann es sein dass sogar 2 Zeilen noch zu wenig sind - hier 3 oder 4 vorzusehen wäre also vermutlich auch nicht total bekloppt.)

    "Ort" ist mehr oder weniger klar.

    Der Name "Bundesland" ist vielleicht nicht optimal, denn je nach Land kommt hier auch der Name einer Provinz, Region, eines Kanton o.ä. rein. Ist zwar alles recht ähnlich, aber nicht 100% identisch mit dem Konzept "Bundesland".

    "Postleitzahl" und "Land" sind auch mehr oder weniger klar.

    Und ganz wichtig dass alles ausreichend lange String Felder sind. Eine Postleitzahl ist halt nicht unbedingt eine Zahl, genau so wie eine Seriennummer nicht unbedingt eine Nummer ist.



  • lol
    ok
    wenn du glaubst



  • ps:
    Wenn du meinst dass der Vorschlag von tenim auch nur irgendwas bezüglich Normalisierung verbessert, dann hast du Normalisierung nicht verstanden.

    Einen einzelnen String ("Or_Ort") in einem Table zu packen und mit einem Surrogate ("Or_ID") zu versehen taugt höchstens zum Speicherplatz Sparen und CPU-Zeit Verheizen.



  • Doch, ich denke schon, dass ich die Normalisierung verstanden habe.

    Deshalb schwebte mir auch eher so etwas vor:

    In der Adresstabelle steht nur die PLZ.

    Zusätzlich gibt es zwei Tabellen:

    tblPLZ
    ------------
    plz - ort_id

    tblORTE
    -------------------
    ort_id | ort_name

    hustbaer schrieb:

    ps:
    Wenn du meinst dass der Vorschlag von tenim auch nur irgendwas bezüglich Normalisierung verbessert, dann hast du Normalisierung nicht verstanden.

    Einen einzelnen String ("Or_Ort") in einem Table zu packen und mit einem Surrogate ("Or_ID") zu versehen taugt höchstens zum Speicherplatz Sparen und CPU-Zeit Verheizen.



  • Wenn du die Normalformen verstanden hast, dann fehlt's vielleicht an der Erfahrung was man alles NICHT über Adressen annehmen sollte.
    Anyway, ich klinke mich aus, da ich nicht den Eindruck habe dass du wirklich 'was dazulernen willst.



  • Der Strassenname alleine ist keine Entity.

    warum? wenn man es genau aufschlüsselt ist alles eine entität.
    beispiel:

    * ein ort hat 0 bis viele straßen
    * in einer strasse gibt es 0 bis viele hausnummern

    den straßennamen selbst in einer tabelle zusammenzufassen macht absolut sinn, egal ob die straße in china, polen oder feuerland liegt. wenn sie exakt gleich heißt wie eine andere kann man das ganze in einem lookup-tabelleneintrag zusammenfassen. das spart extrem speicherplatz, vor allem wenn man millionen von datensätzen hat.

    und wenn sich herausstellt, das zu einem ort die straße xyz falsch eingetragen wurde (rechtschreibfehler) und es mehrere andere datgensätze gibt die sich auch darauf beziehen weil bei denen es zufällig stimmt, dann liegt man für diesen einen datensatz einfach einen neuen eintrag an.

    wikipedia:

    Unter Normalisierung eines relationalen Datenschemas (Tabellenstruktur) versteht man die Aufteilung von Attributen (Tabellenspalten) in mehrere Relationen (Tabellen) gemäß den Normalisierungsregeln (s. u.), so dass eine Form entsteht, die keine vermeidbaren Redundanzen mehr enthält.

    und 1000 mal "münchen" in einer tabelle ist eine vermeidbare redundanz.



  • tenim schrieb:

    warum? wenn man es genau aufschlüsselt ist alles eine entität.
    beispiel:

    * ein ort hat 0 bis viele straßen
    * in einer strasse gibt es 0 bis viele hausnummern

    Du triffst hier falsche Annahmen über Adressformate. Es gibt Adressen ohne Straßenname oder Hausnummer.

    tenim schrieb:

    den straßennamen selbst in einer tabelle zusammenzufassen macht absolut sinn, egal ob die straße in china, polen oder feuerland liegt.

    Und wenn du dann die Adresse in Fragmente zerlegt hast, wie stellst du sicher, dass du sie wieder zusammensetzen kannst? Wie bildest du beispielsweise ab, dass bei einer französischen Adressen die Hausnummer vor dem Straßennamen steht?



  • Du triffst hier falsche Annahmen über Adressformate. Es gibt Adressen ohne Straßenname oder Hausnummer.
    

    dann sind diese beiden felder halt null und das anderen feld, welches für diese fälle existiert hat einen inhalt.

    Und wenn du dann die Adresse in Fragmente zerlegt hast, wie stellst du sicher, dass du sie wieder zusammensetzen kannst? Wie bildest du beispielsweise ab, dass bei einer französischen Adressen die Hausnummer vor dem Straßennamen steht?
    

    ich würde in der adresstabelle noch das land vermerken und dann in der abfrage
    mit "case when" den straßen-string landabhängig zusammenbauen.



  • Was mit einer sauberen Trennung von Ort, Straße, Postleitzahlen und Vorwahl möglich ist lässt sich auf strassenkatalog.de bewundern.

    Genau diese saubere Trennung hätte ich gern in meiner Adressverwaltung 🙂



  • tenim schrieb:

    dann sind diese beiden felder halt null und das anderen feld, welches für diese fälle existiert hat einen inhalt.

    Das wird bestimmt ein übersichtliches Eingabeformular.

    tenim schrieb:

    ich würde in der adresstabelle noch das land vermerken und dann in der abfrage
    mit "case when" den straßen-string landabhängig zusammenbauen.

    Vergiss nicht, dass dein "case when" auch die ganzen optionalen Adressbestandteile richtig zusammensetzen muss. Ich wünsche schon mal viel Spaß.

    Martin22 schrieb:

    Was mit einer sauberen Trennung von Ort, Straße, Postleitzahlen und Vorwahl möglich ist lässt sich auf strassenkatalog.de bewundern.

    Dieses Google-Frontend scheitert an den beiden Straßen mit demselben Namen und derselben Postleitzahl, die es in zwei verschiedenen Orten gibt. Und natürlich ist es auf Adressen in Deutschland beschränkt. Wenn dir das reicht, bitte.



  • Das wird bestimmt ein übersichtliches Eingabeformular.

    wo ist das problem? was soll daran unübersichtlich sein?

    [land] [plz] [ort] [straße] [nr] [adresszusatz1]

    oder meinst du wegen der vielen felder? hast du schon mal mit SAP-R3 gearbeitet? das ist unübersichtlich.
    auderdem ist diese version sogar von vorteil: man kann die eingegebenen daten viel einfacher auf korrektheit testen. das wäre mit einem string, der alles enthält wesentlich aufwändiger.

    Vergiss nicht, dass dein "case when" auch die ganzen optionalen Adressbestandteile richtig zusammensetzen muss. Ich wünsche schon mal viel Spaß.
    

    was soll daran schwer sein?
    select
    case when land='DE' then str+hnr else
    case when land='FR' then hnr+str else
    case when land='Uranda Burundi' then adresszusatz1+hnr+zusatz4+str else
    ...alle anderen ausnahmen
    end
    end
    end
    AS adresse
    from tabelle

    so what?



  • tenim schrieb:

    was soll daran schwer sein?
    select
    case when land='DE' then str+hnr else
    case when land='FR' then hnr+str else
    case when land='Uranda Burundi' then adresszusatz1+hnr+zusatz4+str else
    ...alle anderen ausnahmen
    end
    end
    end
    AS adresse
    from tabelle

    Das funktioniert ja nichtmal in Mannheim. Ja, da kann man jetzt 'ne eigene Ausnahme für hinzufügen. Nur: Wie viele Ausnahmen willst Du noch hinzufügen? Ich tippe mal auf 'ne mindestens dreistellige Zahl, wenn nicht mehr. Siehe https://www.mjt.me.uk/posts/falsehoods-programmers-believe-about-addresses/



  • EDIT: SG1 hat den Link schon gepostet.



  • tenim schrieb:

    und 1000 mal "münchen" in einer tabelle ist eine vermeidbare redundanz.

    Welche Normalform soll es verletzen? Und zitiere mir bitte die Regel die verletzt wird.



  • Guckst du hier: http://home.f1.htw-berlin.de/scheibl/db/RDBMS/normalform.htm#2nf

    hustbaer schrieb:

    tenim schrieb:

    und 1000 mal "münchen" in einer tabelle ist eine vermeidbare redundanz.

    Welche Normalform soll es verletzen? Und zitiere mir bitte die Regel die verletzt wird.



  • Martin22 schrieb:

    Guckst du hier: http://home.f1.htw-berlin.de/scheibl/db/RDBMS/normalform.htm#2nf

    Die Definition auf der Seite ist richtig. Aber Du hast sie anscheinend nicht verstanden.

    Wobei die Seite eh lustig ist:

    Kann ich denn nicht einfach durch Einführung eines chaotischen Schlüssels die 2NF automatisch erfüllen?
    Nein, denn dann liegt automatisch ein Verstoß gegen die 3NF vor.

    wtf?!



  • @Martin22
    Ich fürchte du musst mir schon mit eigenen Worten genau beschreiben was deiner Meinung nach die Verletzung der 2NF sein soll, wenn du möchtest dass ich dich ernst nehme.

    Die 2NF wird nämlich ganz sicher nicht alleine dadurch verletzt dass in einer bestimmten Tabelle in einer bestimmten String-Splate mehrfach der selbe Wert drinnen steht. Genausowenig wie es die 2NF verletzen würde wenn in einer Integer-Spalte mehrfach der selbe Wert steht.

    => Du hast einfach Normalisierung nicht verstanden

    Nochmal: Normalisierung hat nichts mit Surrogates zu tun.


Anmelden zum Antworten