Wie abfragen?



  • Hallo

    Ich bin relativ neu im Umgang mit Datenbanken und stelle deswegen wahrscheinlich eher Grundlagenfragen, aber es muss sein. 😉 Folgendes Szenario:

    Ich habe eine Datenbank mit mehren Tabellen:
    Land (Name, Kurzname, ...)
    Liga (Anzahl Teams, Land, ...) - hier schon meine erste Frage:

    Ist es richtig so, dass man der Liga eine Spalte spendiert, in der steht, zu welchen Land sie gehört?

    Team (Name, Land, Liga,...) - hier wieder das gleiche: Eine Spalte für das Land zu der die Liga gehört und eine Spalte für die Liga. Löst man das so oder geht das eleganter?

    Jetzt würde ich gerne abfragen kreieren, die mir alle Ländernamen liefert, zu denen es mind. ein Team gibt Also mind. ein Team soll dieses Land in der Spalte Land stehen haben. Ist das verständlich?

    chrische



  • Land würde ich eine Autoid verpassen.

    Dadurch kannst du bei Team im Feld Land dann die ID verwenden und muss nicht einen Text schreiben.
    Nennt man dann Normalisierung.
    Genauso verhält es sich mit der anderen Tabelle.

    Eine ID ist ein INT oder BIGINT.
    Braucht weniger Platz als VARCHAR,CHAR oder sonstwas.



  • Hallo

    Okay. Also das Prinzip ist richtig nur die Umsetzung war noch nicht ganz passend? Könnt ihr noch was zu dem Abfrageproblem sagen?

    chrische



  • Ich würde hier auch numerische Schlüssel verwenden

    Land (IDLand, Name, Kurzname, ...)
    Liga (IDLiga, Anzahl Teams, KeyLand, ...)
    Team (IDTeam, Name, KeyLiga,...)

    und ann einfach ein INNER JOIN

    SELECT DISTINCT Land.Name 
    FROM Land
    JOIN Liga ON IDLand=KeyLand
    JOIN Team IN IDLiga=KeyLiga
    

    Die Syntax ist DB-abhängig. Ein Verweis auf Land im Team brauchst Du nicht, das ist implizit über die Liga beschrieben. Würde sonst 3NF verletzen.

    /Edit: DISTINCT



  • Hallo

    Naja eine Verweis zum Land muss schon sein, weil es auch freie Vereine gibt.

    chrische



  • Dann wird diese Abfrage eh' nichts bringen. In diesem Fall wäre KeyLand NULL.



  • Hallo

    Ehrlich gesagt verstehe ich nicht, was du mir sagen willst.

    chrische



  • Du willst ausdrücken, dass es Vereine gibt, die zu einem Land gehören aber nicht zu einer Liga?



  • Hallo

    Genau. Freie Vereine.

    chrische



  • Dann mach doch noch ein KeyLand im Verein 'rein und join darüber.

    SELECT DISTINCT Land.Name
    FROM Land
    JOIN Team IN IDLand=KeyLand
    

    Jetzt kannst Du aber ausdrücken, dass ein Verein aus einem anderen Land als die Liga ist in der der Verein spielt. Also ein russischer Verein könnte in einer englischen Liga spielen. Diese Transitivität "Ligen gehören zu einem Land" und "wenn ein Team in einer Liga spielt, spielt es in dem Land der Liga" ist verletzt. Ich weiss jetzt nicht ob das so modelliert werden soll. Es gibt verschiedene Deutungen. Man könnte, wenn das nicht gewünscht ist, mit einem Constraint sichern, dass wenn ein Team einer Liga zugehörig ist keinen Schlüssel auf ein Land haben darf ... aber dazu kenne ich die Ausgangsbedingungen nicht.



  • Hallo

    So richtig habe ich es immer noch nicht. Bei deiner Abfrage witte müsste ich doch eine ID für eine Land übergeben. Ich will aber, dass alle Länder zurückgegeben werden, in denen es mind. ein Team gibt. Habe ich deine Abfrage falsch verstanden?

    chrische



  • Ich habe mich verschrieben. Es muss ON statt IN heißen. Meinst Du das?



  • Hallo

    Nein das meinte ich nicht. So wie ich de Abfrage verstehe, muss ich doch eine ID übergeben, die dann geprüft wird: IDLand=KeyLand. Ich will ja aber alle Länder, in denen es Vereine gibt:

    Beispiel:

    VereinA (Dtl.)
    VereinB (Eng.)
    VereinC (Eng.)
    VereinD (Spa.)
    VereinE (Dtl.)
    VereinF (Fra.)
    Vereing (Dtl.)

    Sugabe sollte dann sein: dtl., engl, spa., fra.

    chrische



  • Ich bin davon ausgegangen, dass Du numerische Schlüssel verwendest:

    Land:

    IDLand Name
    -----------
     1     pl
     2     gb
     3     fr
     4     d
     5     es
    

    Team:

    IDTeam Name KeyLand 
    -------------------
     1     A    3
     2     B    4
     3     C    4
     4     D    2
     5     E    5
     6     F    2
     7     G    4
    

    Wenn Du jetzt die Anfrage anwendest, erhältst Du dtl., engl, spa., fra.
    Vllt mal ein Buch über Datenbankentwurf durchstöbern.



  • Unix-Tom schrieb:

    Land würde ich eine Autoid verpassen.

    Dadurch kannst du bei Team im Feld Land dann die ID verwenden und muss nicht einen Text schreiben.
    Nennt man dann Normalisierung.
    Genauso verhält es sich mit der anderen Tabelle.

    Eine ID ist ein INT oder BIGINT.
    Braucht weniger Platz als VARCHAR,CHAR oder sonstwas.

    Normalisierung hört sich an, als würdest Du Dich auskennen. Dann kannst Du mir bestimmt verraten, welche Normalisierungsregel sagt, welchen Datentyp ein Schlüsselfeld haben muß.



  • keine Normalisierung gibt an welche welcher Datentyp verwendet werden soll.
    Sondern es kommt darauf an ob Attribute aus der realen Welt als Schlüsselfelder verwendet werden soll, oder ob ein Hilfs-Attribut verwendet (INT, GUID) wird, um ein Datensatz eindeutig bestimmbar zu machen.
    Erster Ansatz vermeidet Dubletten aus der realen Welt, zweiter Ansatz ermöglicht die Datenbank Performance besser ausnutzen zu können. Der Primary Index über INT/GUID ist wesentlich performanter, als über char/text.



  • Grundsätzlich sagt normalisierung aus das man nicht gleiche Daten in verschiedenen Tabellen haben soll.

    Man braucht nicht

    Tabelle Kunden mit

    Name, Ort
    ich Hamburg

    Tabelle Mitarbeiter mit
    Name, Ort
    Du Hamburg

    sondern
    Tabelle Orte
    id, ort

    1 hamburg

    Tabelle Kunden mit

    Name, Ortid
    ich 1

    Tabelle Mitarbeiter mit
    Name, Ortid
    Du 1

    Wenn sich der Name des Ortes ändert dann reicht es in einer Tabelle den Namen zu ändern und es passt dann in jeder Tabelle
    Dies ist einer der Fälle.

    Es gibt aber eben verschiedene Stufen der Normalisierung.
    IMHO 9.

    Gebräuchlich sind bis Stufe 5.
    Ich halte es max. bis Stufe 3 für Sinnvoll.
    Kommt aber auf das DB-Design an.
    Kann auch Fälle geben wo mehr Stufen Sinn macht.
    Gibt keine Allgemeine Aussage.

    Genauere Def. bitte bei WIKI anschauen.



  • ScaniaV8 schrieb:

    keine Normalisierung gibt an welche welcher Datentyp verwendet werden soll.
    Sondern es kommt darauf an ob Attribute aus der realen Welt als Schlüsselfelder verwendet werden soll, oder ob ein Hilfs-Attribut verwendet (INT, GUID) wird, um ein Datensatz eindeutig bestimmbar zu machen.
    Erster Ansatz vermeidet Dubletten aus der realen Welt, zweiter Ansatz ermöglicht die Datenbank Performance besser ausnutzen zu können. Der Primary Index über INT/GUID ist wesentlich performanter, als über char/text.

    Darauf wollte ich hinaus. Es nennt sich also nicht "Normalisierung", wenn ich dem Land eine nummerische ID vergebe.

    Ich möchte auch bezweifeln, daß ein nummerisches feld wesentlich schneller ist, als ein char-Feld. Gerade bei der Länderdatenbank könnte man beispielsweise die internationalen Länderkennungen "D", "F", "GB" usw. verwenden. Ein char(3)-Feld ist wahrscheinlich nicht wesentlich langsamer, dafür aber einfacher in der Handhabung, da die Schlüssel sprechender sind. So ganz nebenbei verhindert das auch noch, daß ich 2 mal Deutschland anlege, was bei einem Kunstschlüssel durchaus passieren kann.

    Wenn man jetzt performancemässig ganz pingelig sein wollte, kann man davon ausgehen, daß ein char(3)-Feld wahrscheinlich 3 Bytes benötigt. Ein Längenfeld ist hier nicht notwendig, da diese fix ist. Ein Integer hat 4 Bytes. Also passen auf einen Sektor der Festplatte mehr Schlüsselfelder. Das bedeutet weniger I/O und ist damit schneller.

    Ein globales "nummerische Felder sind schneller als char-Felder" würde ich daher nicht so einfach stehen lassen. Wichtiger ist die fachliche Richtigkeit.



  • Ich möchte auch bezweifeln, daß ein nummerisches feld wesentlich schneller ist, als ein char-Feld

    Bei Datenbanken die verschiedene Collation-Sequences unterstützen (und nicht einfach "binary" sortieren) sind jegliche String-Felder *wesentlich* langsamer als integer oder binary Felder. Der Grund ist dass jeder String zum Sortieren/Vergleichen erstmal umgewandelt werden muss, dieser Vorgang nicht grad CPU-schonend ist, und der umgewandelte String gleich 3x soviel Platz braucht (wenn ich mich richtig erinnere 3x 16 Bit pro Zeichen).
    Dafür gehen dann - je nach Collation-Sequence - auch so Sachen wie "ABcdê" == "abCDE".

    Bei ausreichend kurzen Keys, und vor allem wenn die Abfragen nicht CPU limitiert sind, wird es aber wahrscheinlich völlig wurscht sein 🙂

    Andrerseits würde ich keine komplizierten JOINS/GROUP BYs mit recht langen Strings (z.B. komplette URLs oder UNC Pfade) machen, wenn die Abfrage sehr sehr oft ausgeführt wird.



  • @chrische:
    Ich find deinen Ansatz ok. Da es eben in der Tat so freie Vereine gibt bzw. auch so Szenarien gibt, in welcher ein Verein in einer Liga eines anderen Landes mitspielt (z.B. spielt San Marino als Verein in der ital. Liga, obwohl es ein anderes Land ist), ist das okay, dass man da sowohl bei Liga als auch bei Verein eine Spalte für das Land hat.
    Ob du die Tabelle für Länder nun mit numerischen Schlüsseln aufbaust oder mit den Abkürzungen als Primärschlüssel (de, us, usw...) ist denke ich egal. Ich würde letzteres machen, da das ja meines Wissens auch eindeutig ist.

    Was du evtl noch bedenken könntest, ist, dass es evtl. Vereine gibt, die in mehreren Ligen spielen, d.h. wenn du ganz flexibel sein willst machst du noch ne extra Tabelle, wo quasi nur die Vereine den Ligen zugeordnet sind (d.h. diese Zuordnung ist nicht direkt in der Vereins-Tabelle via Fremdschlüssel abgebildet).


Anmelden zum Antworten