SQL-Problem 2. Normalform



  • 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.



  • Das funktioniert ja nichtmal in Mannheim.

    sicher funktioniert das. hast du wenigstens anfängerkenntnisse in sql?
    und ja, polemik (mannheim) ist bei vielen oft das einzige mittel, wenn sie nicht mehr weiter wissen. arm.

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

    ich habe nicht gesagt, das eine normalform verletzt wurde, sondern nur, das es eine redundanz ist, die durch eine lookup-tabelle vermieden werden kann und das man damit speicherplatz spart.

    wikipedia zu redundanzen in datenbanken (wichtiger teil ist fett):

    Durch Normalisierung des Datenbankschemas können Redundanzen weitgehend vermieden werden. Es gibt auch Redundanzen, die unvermeidbar sind (zum Beispiel Schlüsselredundanzen) und daher als notwendiges Übel in Kauf genommen werden. Es gibt auch Redundanzen, die in Kauf genommen werden, weil deren Vermeidung einen zu hohen Aufwand im Verhältnis zu ihrer Problematik darstellen würde, wie zum Beispiel das mehrfache Auftreten eines Attributwertes oder die doppelte Speicherung des Namens Müller für Herrn Müller und für Frau Müller.
    Die absichtliche Inkaufnahme von Redundanz zur Gewinnung einer besseren Leseleistung nennt man Denormalisierung.

    das beispiel mit münchen oder straßennamen ist so eine sache mit absichtlicher inkaufnahme von redundanzen, da es oft mehr aufwand machen würde mit lookup-tabellen zu arbeiten als ohne. deshalb schrieb ich auch in meinem ersten antwortpost zum op

    ob das dann alles sinnvoll ist, steht auf einem anderen blatt.



  • tenim schrieb:

    Das funktioniert ja nichtmal in Mannheim.

    sicher funktioniert das. hast du wenigstens anfängerkenntnisse in sql?

    Hast Du meinen Link überhaupt angeklickt? Meine Kritik bezog sich nicht auf Deine SQL-Syntax. Meine Kritik bezog sich darauf, dass Du davon ausgegangen bist, dass eine Adresse immer eine Straße beinhaltet.

    und ja, polemik (mannheim) ist bei vielen oft das einzige mittel, wenn sie nicht mehr weiter wissen. arm.

    ROFL


Anmelden zum Antworten