Hagen: Normaliesierung

Hallo,
es ist ein Freitag morgen und ich sitz hier bei meinem Praktikum und hab nix zu tun... deshalb wollte ich mal n bissel was für die grauen zellen tun und was "php-schustern". Hier mein gewähltes Problem-meine Ellis haben ne Gaststätte-es ist WM- und von UrKrostizer gibts son komisches Gewinnspiel-wer am besten beim tippen von ergebnissen ist kann ne Reise gewinnen oder so...
Nur ist das "Ausrechenprogramm" was die mitgeschickt habe besch... . Also sag ich "mutti ich bau dir n neues". Und da steh ich nun.
Zunächst will ich mich auf die Vorrunde beziehen:
Spieler können tippen für beliebige noch kommende Spiele, tipp richtig=3pkt.; Tendenz=1pkt; sonst 0;
Es wurde auch schon getippt die alten Tipps müsste ich von hand nachtragen. oder halt dann über das Programme aber das ist erstmal egal.
Es soll immer eine Tabelle wer gerade führend ist zu sehen sein.
Nun gehts mir um die Tabellenstruktur und wie sie am sinnvollsten wäre, dabei würde ich mich gern an die "Normalisierungsregeln" halten ums wenigstens einmal richtig zu machen, meine IDEE:
1. TAB: Spieler
ID NAME PUNKTE
2. TAB:Spiele
ID MANNSCH1 MANNSCH2 TORE1 TORE2
3. TAB:Tipps
SPIELID SPIELERID TIPPTORE1 TIPPTORE2

So nun meine Frage wie ließe sich diese Tabelle normaliesieren?
Soweit ich das sehe ist die 1NF erfüllt. alle Einträge wären "ATOMAR". 2NF: Seh ich schon in der ersten Tabelle ein Problem PUNKTE ist nicht von NAME abhängig sondern würde eher in TAB 3 passen?

Naja schonmal vielen dank für eure Tipps...

MFG HAgen

  1. Hallo,

    du könntest die Mannschaften in eine eigene Tabelle normalisieren,
    also:

    Tab "Mannschaft"
    Id, Name
    ---------
    1, Schweiz
    2, Trinidad & Tobago
    3, Vietnam

    Tab "Spiel"
    Id, Mannschaft1Id, Mannschaft2Id
    ---------------------------------
    1, 1, 2
    2, 1, 3
    3, 2, 3

    Da zum Glück pro Partie nur 2 Mannschaften gegeneinander spielen,
    gibt es definitiv keinen realen Nutzen Tipps sowie Spielergebnisse
    in eine vertikale Ausrichtung (Zeilen statt Spalten) zu bringen.

    Für eine Auswertung mit dem Mannschaftsnamen müsstest du dann
    allerdings die Tabelle Mannschaften 2mal zur Tabelle "Spiel"
    joinen.

    Der Rest der Auswertung ist dann nur noch ein recht einfaches
    "SELECT" mit ein paar arithmetischen Operationen hinsichtlich
    der Tore.

    Und [Punkte] ist sehr wohl von [Name] abhängig. Jeder Name kann
    eine unterschiedliche Punktzahl haben.

    Ciao, Frank

    1. Hallo,
      ja auf die sache mit den mannschaften bin ich grad auch schon beim ersten programmieren gekommen...

      Danke für deine Antwort
      MFG Hagen

  2. Hallo Hagen,

    Nur ist das "Ausrechenprogramm" was die mitgeschickt habe besch... . Also sag ich "mutti ich bau dir n neues". Und da steh ich nun.

    Ich habe hier immer Freitags oder in der Mittagspause mit einem Kollegen in einem kleinen Wettbewerb ein WM-Tippspiel zusammengebastetlt: Er mit MySQL und PHP und meine Wenigkeit mit Access und ASP.NET.

    Hier meine Lösung für die Datenbank:

    Tab1: [teams]
      teamabbreviation (PK)
      teamname
      [group]
      [rank]
      [lot]

    Tab2: [games]
      gameid (PK)
      teamhome
      teamaway
      scorehome
      scoreaway
      addinfo
      penaltyhome
      penaltyaway
      venue
      gamedate
      gameplayed

    Tab3: [bets]
      userid (PK)
      gameid (PK)
      bethome
      betaway
      points
      [timestamp]

    Aus den Tabellen läßt sich über Views und parametriesierbare Abfragen alles wunderschön herleiten. Einfachste Übung ist eine Punkterangliste:

    SELECT users.userid, SUM(bets.points) AS points
    FROM users LEFT JOIN tips ON users.userid=bets.userid GROUP BY users.userid ORDER BY SUM(bets.points) DESC

    Für die Ausgabe der Gruppentabellen muss man etwas überlegen. Habe mehrere Views angelegt, um die siegreiche und unterlegene Mannschaft rauszubekommen, hier ein Bspl für die "hometeamwins":

    SELECT gameid, teamhome, teamaway, scorehome, scoreaway, gameplayed
    FROM games
    WHERE (scorehome>scoreaway AND games.gameplayed=True)

    Die Heim- und Auswärtssiege habe ich dann zu "wins" geuniont:

    SELECT gameid, teamaway as winner, teamhome as looser, scoreaway as winnergoals, scorehome as loosergoals FROM awayteamwins WHERE gameid<49 UNION select
    gameid, teamhome as winner, teamaway as looser, scorehome as winnergoals, scoreaway as loosergoals FROM hometeamwins WHERE gameid<49

    Dann wieder eine Union wins, draws und losses zu "groupphasegames":
    SELECT  * FROM wins UNION SELECT * FROM losses UNION SELECT * FROM draws

    Die daraus entstehende view kann man dann mit der TeamTab joinen zu "view_tablegoals":
    SELECT teams.teamabbreviation, Count(groupphasegames.looser) AS numbergamesplayed, Sum(groupphasegames.winnergoals) AS goalsshot, Sum(groupphasegames.loosergoals) AS goalsconceded, ([goalsshot])-([goalsconceded]) AS goaldifference
    FROM teams LEFT JOIN groupphasegames ON teams.teamabbreviation=groupphasegames.winner
    GROUP BY teams.teamabbreviation

    Dann benötigt man noch die Anzahl der Siege, Niederlagen und Unentschieden pro Team, zB:
    SELECT teams.teamabbreviation, Count(wins.winner) AS numberwins
    FROM teams LEFT JOIN groupphasegames ON teams.teamabbreviation=wins.winner GROUP BY teams.teamabbreviation

    Daraus kann man sich wiederum die Punkte errechnen als "view_tablepoints":
    SELECT teams.group, teams.teamname, teams.teamabbreviation, numberwins.numberwins, numberdraws.numberdraws, numberlosses.numberlosses, ((numberwins.numberwins*3)+(numberdraws.numberdraws*1)) AS points
    FROM ((numberlosses INNER JOIN teams ON numberlosses.teamabbreviation = teams.teamabbreviation) INNER JOIN numberwins ON teams.teamabbreviation = numberwins.teamabbreviation) INNER JOIN numberdraws ON teams.teamabbreviation = numberdraws.teamabbreviation
    ORDER BY ((numberwins.numberwins*3)+(numberdraws.numberdraws*1)) DESC

    Und zum Schluss dann noch der Join zwischen den Views view_tablegoals und view_tablepoints....

    Mit ein bisschen Nachdenken eigentlich ganz logisch...;o)

    Gruß
    LeKuchen

  3. yo,

    1. TAB: Spieler
      ID NAME PUNKTE

    punkte hat schon mal gar nichts in keiner tabelle verloren, weil es sich hier um einen errechneten wert handelt. diese spalte fliegt also komplett raus und wird später durch einen einzigen select für alle spieler erzeugt. und da es ja grundsätzlich um die Liste geht, wer am besten getippt hat, kannst du dir die tabelle spieler auch ganz sparen und anstelle die ID als fremdschlüssel in der Tipp tabelle zu führen, schreibst du dort die klarnamen rein. somit haben wir uns schon mal eine tabelle komplett gespart. es sei den, du willst auch eine ausgabe haben für personen, die keinen tipp abgegeben haben. aber das würde irgendwie keinen sinn machen.

    1. TAB:Spiele
      ID MANNSCH1 MANNSCH2 TORE1 TORE2
    2. TAB:Tipps
      SPIELID SPIELERID TIPPTORE1 TIPPTORE2

    diese zwei tabellen brauchen wir wirklich, weil zwischen den beiden entitäten eine 1:n bezeihung besteht. anstelle der spielerid in der zweiten tabelle kommt dort der klarname der jeweiligen person rein. allerdings können wir uns heir auch die mannschaften sparen, wenn du nur die liste brauchst. was übrig bleibt ist folgendes.

    tabelle spiele:
    ID, Tore1, tore2

    tabele tipps:
    Tipper, spiele_id, tipptore1, tipptore2

    wobei in der zweiten tabelle, tipper und spiele_id zusammen einen primary key bilden und spiele_id natürlich der fremdschlüssel auf die erste tabelle ist.

    diese beiden tabellen mit den spalten reichen aus, um deine liste auszugeben.

    Ilja