kostenloser Webspace werbefrei: lima-city


Stichwort nur einmal ausgeben

lima-cityForumProgrammiersprachenPHP, MySQL & .htaccess

  1. Autor dieses Themas

    fabian-riedel

    Kostenloser Webspace von fabian-riedel

    fabian-riedel hat kostenlosen Webspace.

    Hallo,
    ich habe eine MySQL tag/tabelle">Tabelle, in der Spiele gespeichert sind. Diesen Spielen sind außerdem noch "Tags" zugeordnet, welche mit Kommas getrennt sind (outdoorspiele, kreisspiele, sinnesspiele,). Nun möchte ich eine Übersichtsseite erstellen, auf der die Tags aller Spiele aufgelistet sind, allerdings nicht doppelt.
    Wie löse ich dieses Problem am besten?

    Grüßle Fabi
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. du könntest zuerst die komplette tabelle mit den spielen durchgehen, und die tags aufgesplittet in ein array einfügen.
    dabei gibt es zwei möglichkeiten:
    1. du schaust vor dem einfügen, ob das element schon im array vorhanden ist, wenn nicht fügst du es ein
    2. du fügst einfach alles ein, und löscht nachträglich alles doppelte raus.

    was am ende performanter ist hängt meiner meinung nach auch von der datenmenge ab.

    mfg
  4. Autor dieses Themas

    fabian-riedel

    Kostenloser Webspace von fabian-riedel

    fabian-riedel hat kostenlosen Webspace.

    syberpsace schrieb:
    1. du schaust vor dem einfügen, ob das element schon im array vorhanden ist, wenn nicht fügst du es ein


    Und wie mache ich das? Bin Leider kein PHP-Profi...
    Grüßle Fabi
  5. dazu gibt es die schöne funktion array_unique().
    damit kannst du das ganze einfach lösen...wie schon gesagt, weiß ich aber nicht, ob das die schönere meiner beiden angebotenen lösungen ist.

    €dit: sry...verlesen
    fürs überprüfen vor dem einfügen gibt es leider keine so schöne fuktion, da müsstest du dir selbst was basteln.


    mfg

    Beitrag zuletzt geändert: 18.1.2010 17:50:52 von syberpsace
  6. Am besten siehst du dir an, was Normalformen sind, insbesondere die erste Normalform sollte dich interessieren. Diese tritt ein, wenn deine Attribute atomisch sind.

    Oder im Klartext: Wenn du ordentlich arbeiten willst, musst du die Tags in eine extra Tabelle auslagern und eine Linker-Tabelle erstellen, die Tag und Spiel verbinden.

    Dann kannst du auch die volle Macht von SQL nutzen und ein SELECT DISTINCT durchführen.
  7. Autor dieses Themas

    fabian-riedel

    Kostenloser Webspace von fabian-riedel

    fabian-riedel hat kostenlosen Webspace.

    nikic schrieb:
    Am besten siehst du dir an, was Normalformen sind, insbesondere die erste Normalform sollte dich interessieren. Diese tritt ein, wenn deine Attribute atomisch sind.

    Oder im Klartext: Wenn du ordentlich arbeiten willst, musst du die Tags in eine extra Tabelle auslagern und eine Linker-Tabelle erstellen, die Tag und Spiel verbinden.

    Dann kannst du auch die volle Macht von SQL nutzen und ein SELECT DISTINCT durchführen.


    Ja das hatte ich mir auch schon überlegt, allerdings wusste ich auch da nicht, wie ich das machen solle. :-(
    Hat da jemand ne Lösung?

    Danke im Vorraus Fabi
  8. Also wenn mich nicht alles täuscht hängst du an deine Select Abfrage einfach "Group By "TAG" " an und schon sollte es nurnoch jeden Tag einmal ausgeben.

    Auch bei unsortierten Listen welche nicht in 1. Normalform sind. Hab das grade mal bei mir getestet und es scheint zu funktionieren.
  9. Berndsbande.
    Wenn in der einen Zeile als Tag steht: Muh, Blub, Mäh, und in der anderen Muh, Grr, Mäh, dann hat er Muh und Mäh trotzdem doppelt.

    Du erstellst eine Tabelle Spiele:
    spielID, spielname, sonstiges

    Eine Tabelle (Tags)
    spielID, tag

    Du erstellst also ein Spiel, mit einer ID
    Dann gibst du in Tabelle "Tags" für jeden Tag einmal die SpielID und einmal den Tag ein.

    Zuletzt kannst du jetzt die Abfrage machen: SELECT tag FROM Tags GROUP BY tag


    Willst du die zum Tag zugehörigen Spiele sammeln müsste das (bin da nicht ganz Fit) damit gehen:
    SELECT spielname FROM Spiele, Tags WHERE Spiele.spielID = Tags.spielID AND Tags.tag = $gewünschter Tag


    Angaben ohne gewähr.


    lg,
    Antagonist

    PS: Lass mich wissen, ob es funktionierte!
  10. Autor dieses Themas

    fabian-riedel

    Kostenloser Webspace von fabian-riedel

    fabian-riedel hat kostenlosen Webspace.

    frodo89 schrieb:
    PS: Lass mich wissen, ob es funktionierte!


    Ich denk schon dass es funktioniert hätte, allerdings müsste ich dazu ja die Tags nochmal in eine extra Tabelle schreiben.
    Gibt es denn keine Möglichkeit was mit PHP zu schreiben, das die Tags dann aus der Spieletabelle ausliest, in einen Array einliest (oder so - hab da wenig Ahnung) und diese Tags dann in einer extra Tabelle speichert wo diese dann per SELECT DISTINCT ausgelesen werden können?

    Grüßle Fabi
  11. frodo89 schrieb:
    Berndsbande.
    Wenn in der einen Zeile als Tag steht: Muh, Blub, Mäh, und in der anderen Muh, Grr, Mäh, dann hat er Muh und Mäh trotzdem doppelt.

    Du erstellst eine Tabelle Spiele:
    spielID, spielname, sonstiges

    Eine Tabelle (Tags)
    spielID, tag

    [...]


    Das ist auch falsch. ;-)
    Bei der Beziehung handelt es sich um eine n-m Beziehung: Einem Tag können belieblg viele (verschiedene) Spiele zugewiesen werden. Einem Spiel können beliebig viele (verschiedene) Tags zugewiesen werden.
    D.h. du brauchst drei Tabellen.
    =>
    Table spiel:
    spiel_id, spiel_name, spiel_sonstiges

    Table tag:
    tag_id, tag_name

    Table spielTagRelation:
    spielTagRelation_spiel_id, spielTagRelation_tag_id


    Beispiel:
    spiel_id: 1
    spiel_name: Tetris
    ...
    spiel_id 2
    spiel_name Mario

    tag_id 1
    tag_name: Geschicklichkeit
    tag_id 2
    tag_name: Jump'n'Run

    spielTagRelation_spiel_id 1
    spielTagRelation_tag_id 1
    spielTagRelation_spiel_id 2
    spielTagRelation_tag_id 1
    spielTagRelation_spiel_id 2
    spielTagRelation_tag_id 2


    D.h. Tetris ist ein Geschicklichkeitsspiel.
    Mario ist ein Geschicklichkeitsspiel und ein Jump'n'Run Spiel.

    VG Lucas

    P.S.: Mein Karma ist ganz schön niedrig... ;-)


    edit:
    Dadruch steht in der Tabelle Tags nicht dreimal "Geschicklichkeit", sondern nur einmal.
    Folglich reicht es die Tabelle Tags auszulesen, um zu wissen, wie viele verschiedene Tags es gibt.

    Beitrag zuletzt geändert: 21.1.2010 4:39:54 von lucas9991
  12. warum denn das?
    Warum musst du einem eindeutigen Tag eine eindeutige ID zuweisen, und verwendest den Tag nicht selbst als ID, und sparst dir dafür Zeit bei der Abfrage, und Speicherplatz wegen weglassen unnötiger Daten.


    Also sind wir soweit, das wir sehen, das man dem Tag nicht noch eine Zahl zuweisen muss, nur weil man es kann...
    Warum müssen wir dann eine Tabelle mit nur einer Spalte erstellen, um diese über eine andere Tabelle zu verlinken?
    Die Abfrage der 3. Tabelle mit den Tagnamen kann man sich also spaaren.

    Warum schmeißen wir die Tabelle dann nicht gleich raus?

    @Fabian:
    schattenbaum.net sagt:
    <?php
      $abfrage = "SELECT url, urlname FROM links";
      $ergebnis = mysql_query($abfrage);
      while($row = mysql_fetch_object($ergebnis))
        {
        echo $row->url;
        }
      ?>


    Statt dem echo fügst du den Eintrag einem Array hinzu.
    Statt -> url verwendest du halt ->tag

    Danach kommt
    $tagarray = array_unique($tagarray)

    PS: Ich beherrsche kein PHP


    lg,
    Antagonist

    Beitrag zuletzt geändert: 21.1.2010 11:14:41 von frodo89
  13. frodo89 schrieb:
    warum denn das?
    Warum musst du einem eindeutigen Tag eine eindeutige ID zuweisen, und verwendest den Tag nicht selbst als ID, und sparst dir dafür Zeit bei der Abfrage, und Speicherplatz wegen weglassen unnötiger Daten.


    Also sind wir soweit, das wir sehen, das man dem Tag nicht noch eine Zahl zuweisen muss, nur weil man es kann...
    Warum müssen wir dann eine Tabelle mit nur einer Spalte erstellen, um diese über eine andere Tabelle zu verlinken?
    Die Abfrage der 3. Tabelle mit den Tagnamen kann man sich also spaaren.

    Warum schmeißen wir die Tabelle dann nicht gleich raus?

    [...]

    Man benötigt eine dritte Tabelle weil die Beziehung zwischen den Spielen und den Tags eine n-m Beziehung (n,m Elemnt aus den natürlichen Zahlen) ist.
    Jedenfalls sollte man es als n-m Beziehung ansehen, dadurch werden Redundanzen vermieden.

    Beispiel:
    Du hast zwei Speile und beide Spiele sind Geschicklichkeitsspiele.
    Wenn du jedem Tag ein Spiel zuweist, dann muss das Tag "Geschicklichketisspiel" zwei mal in der Tabelle Tags vorhanden sein.
    Das heißt du hast zwei Einträge in Tags, die sich lediglich durch die ID unterscheiden. => Das nennt man Redundanz und ist meist unerwünscht, da dadurch schnell Fehler passieren und es auch nicht Effizient ist.

    Darüberhinaus kann man durch dieses Datenbankschema die gewünschten Ausgaben viel leichter und dadurch effizienter abfragen.
  14. Eine ID muss nicht unbedingt eine Zahl sein.
    Du kannst den Tag selbst, da er eine Eindeutige Bezeichnung ist, und damit so einmalig ist, wie die ID
    als ID verwenden.

    Was du vor hast, ist in meinen Augen so sinnlos, wie IDs IDs zuzuweisen, um mit deren IDs eine Verknüpfung zur ID der ID der ID von blub aufzubauen.

    Es ist egal, ob du in die Link-tabelle 30 mal ID 2003 eingibst, oder 30 mal Geschicklichkeitsspiel.

    Redundanz würde erst entstehen, wenn du bei den Tags eine Beschreibung dessen mitlieferst - was bei Tags ungewöhnlich ist.
    Und selbst dann würde, so sich die Namen nicht überschneiden dürfen - die Tags selbst als ID empfehlen.

    Die ID als Zahl einzuführen macht eigentlich nur Sinn, wenn nicht absolut sichergestellt ist, das es nicht einen anderen eindeutigen Schlüssel gibt.
    Wenn wir z.B. 2 Spiele namens Fangen haben dann brauchen wir für die Spiele eine ID, um z.B. die beiden Fangen von einander zu trennen.
    Sollte aber bereits von Anbegin der Zeit, endgültig festgelegt werden, das der Name des Spiels das Spiel eindeutig benennt, so können wir uns auch in dieser Tabelle die ID spaaren.

    Redundanz:
    Redundanz (latein. redundare „im Überfluss vorhanden sein“) bezeichnet grundsätzlich einen Zustand von Überschneidung oder Überfluss. Es hat in verschiedenen Gebieten eine spezifische Bedeutung:


    Nach dieser Definition würde eine zusätliche ID eine Redundanz darstellen, da wir Eindeutige Bezeichner im überfluss haben, die sich in ihrer Funktionalität 100% überschneiden.


    lg,
    Antagonist
  15. Autor dieses Themas

    fabian-riedel

    Kostenloser Webspace von fabian-riedel

    fabian-riedel hat kostenlosen Webspace.

    S******!
    Wollt ihr mich umbringen?
    Ich bin schwer überfordert...
    Muss denn das alles so kompliziert sein?
    Geht das denn nicht so dass ich alle Tags aus allen Tabellenspalten auslese, diese mit explode() in einen Array einles und dann die einzelnen Tags ein eine neue Tabelle einlese. Dort kann ich sie dann einfach mit SELECT DISTINCT einzeln ausgeben.
    Geht das so irgendwie?

    Grüßle Fabi
  16. Dann hast du die Tags ja einfach in ner Tabelle, aber nichtmehr mit den Spielen in Beziehung gesetzt.

    Wenn du sie in deinem Array hast,
    dann kannst du - wie schon öfters angesprochen,
    mit der Funktion array_unique() einen weiteren Array erstellen lassen, in dem jeder Tag nur einmal vorkommt.

    das sieht dann etwa so aus:
    $array_tag_unique = array_unique($array_tags_multiple)

    oder ähnlich.

    Es wäre schön, wenn wir das ganze hier so unblutig wie möglich über die Bühne bringen können.
    Ich versuche eigentlich Tote zu vermeiden. Wäre schön, wenn du rechzeitig zum Arzt gehst :D
    Ich könnte niemals mit dem Gedanken Leben, für deinen Tod verantwortlich zu sein.


    lg,
    Antagonist
  17. frodo89 schrieb:
    Eine ID muss nicht unbedingt eine Zahl sein.
    Du kannst den Tag selbst, da er eine Eindeutige Bezeichnung ist, und damit so einmalig ist, wie die ID
    als ID verwenden.

    Was du vor hast, ist in meinen Augen so sinnlos, wie IDs IDs zuzuweisen, um mit deren IDs eine Verknüpfung zur ID der ID der ID von blub aufzubauen.
    [...]

    Das ist eine völlig normale Technik und in keinster Weise sinnlos.
    http://www.sqldocu.com/nine/relationship.htm (Thema m:n Beziehung)


    Es ist egal, ob du in die Link-tabelle 30 mal ID 2003 eingibst, oder 30 mal Geschicklichkeitsspiel.

    Nein, das ist es nicht. "2003" ist eine Zahl und wird somit als integer abgespeichert.
    "Geschicklichkeitsspiel" ist ein Zeichenkette und wird als string abgespeichert.
    Schon auf Grund der Performance und Größe ist eine ID vorzuziehen.

    Wie willst du ein Datenbankschema erstellen ohne Redundanz im Bezug auf den Tagnamen?
    Sobald du zwei Spielen den Tag "Geschicklichkeit" zuweisen willst, gibt es eine Redundanz des Tagnamens.
    Tag Tabelle:
    Id Tag
    1 Geschicklichkeit
    2 Geschicklichkeit
    => Redundanz des Tagnamens
    => es handelt sich um eine n-m Beziehung
    => Lösung durch eine dritte Tabelle die Tabelle1 mit Tabelle2 verknüpft
    => siehe meine Lösung


    edit:
    Nur um es eben klar zu stellen. Deine Lösung ist nicht falsch, sie funktioniert, aber sie ist nicht optimiert.

    Beitrag zuletzt geändert: 22.1.2010 3:00:24 von lucas9991
  18. Autor dieses Themas

    fabian-riedel

    Kostenloser Webspace von fabian-riedel

    fabian-riedel hat kostenlosen Webspace.

    frodo89 schrieb:
    Dann hast du die Tags ja einfach in ner Tabelle, aber nichtmehr mit den Spielen in Beziehung gesetzt.


    Die Tags müssen auch garnicht mit den Spielen in Beziehung gebracht werden - dass könnte ich hinterher sowieso so lösen:
    $abfrage = "SELECT * FROM jungscharspiele WHERE tags LIKE '%" . $_GET["tag"] . "%'";


    Die Tags sollen nur nicht mehrmals ausgegeben werden und getrennt werden...

    Grüßle Fabi
  19. lucas:
    Ich weiß nicht, in wieweit der Vorteil, das es sich dabei um INT handelt, die zusätzliche Abfrage wett macht.

    Nach deiner Lösung benötigst du ja eine Abfrage der Relationstabelle, und eine für die jeweils über diese verknüpfte Tabelle.
    Damit kommen wir auf 3 Abfragen.

    Am ende Fragst du aber doch auch die Strings ab.

    Wenn du nur 2 Tabellen hast, spaarst du dir eine Abfrage.
    Je nach Server könnte das Idealer sein.

    Solange du keine weiteren Daten zum Tag hinzufügst (Kurzbeschreibungen o.Ä.) vermute ich,
    das die benötigte Zeit des gesammten Prozesses geringer sein dürfte, als bei den 3 Tabellen.
    Auch wenn dabei weniger Speicher benötigt wird.

    Dazu hab ich aber noch keine Performance-Tests gesehen.

    Es dürfte wohl auch von der Datenmenge abhängen.
    Immerhin kommen noch die zusätzlichen Daten für die Tabellenstruktur dazu.
    Auch da weiß ich aber nicht, in wie weit sich das auswirkt bei der Gesammtgröße der Datenbank.

    Letzten Endes ist mir das aber egal...
    Ich schätze das der Effekt der einen oder anderen Lösung sehr minimal Ausfallen dürfte, da es sich hier ja nur um eine einfache Abfrage handelt.
    Deine Methode ist sicher die eher Standartisierte, da sie sich universell einsetzen lässt.
    Ob es in diesem Fall zu einer besseren Performance beiträgt, kann fabian ja berichten, falls er umstellt, und beide möglichkeiten ausprobiert.


    Oder mir irgendjemand hier vorrechnen...


    @Fabian: Ja: unique_array sorgt genau dafür DAS ES NICHT mehrmals ausgegeben wird.
    Der Rest hier ist eine Diskussion was eine bessere lösung wäre.
    Es wäre wohl auch nicht schwer, deine Tabelle entsprechend zu konvertieren.
    Willst du das nicht: unique_array macht dein leben schöner.


    lg,
    Antagonist

    Beitrag zuletzt geändert: 25.1.2010 15:08:05 von frodo89
  20. @frodo: lucas Herangehensweise ist korrekt. Ich hab auch immer gedacht, dass man IDs nicht zu verteilen hat, aber dem ist nicht so.

    Erstmal musst du bedenken, dass einem Tag weitere Informationen zugeordnet werden können. Beispielsweise eine Beschreibung, Bewertung, usw. Nur weil es zur Zeit nicht so ist, heißt es nicht, dass es sich nie ändern wird. Wenn du dann plötzlich eine Beschreibung speichern willst, dann speicherst du große Mengen an Information redundant.

    Sprich, du kommst nicht darum herum eine Tag-Relation anzulegen.

    Wenn diese nun besteht, ist es nicht klug ein VARCHAR als PRIMARY zu setzen.

    EIN UNSIGNED (...)INT als PRIMARY mit AUTO_INCREMENT ist schneller und platzsparender, da ein INT, bei Tags vielleicht sogar ein SMALLINT kleiner ist als ein VARCHAR(30). (Und noch ein Paar MySQL-interne Vorteile, die es zwar gibt und die entscheidend sind, ich sie aber ohne längeres Suchen nicht belegen könnte.)
  21. frodo89 schrieb:
    lucas:
    Ich weiß nicht, in wieweit der Vorteil, das es sich dabei um INT handelt, die zusätzliche Abfrage wett macht.
    [...]

    Du vergisst den Vorteil von SQL im Bezug auf simple Textdateien.
    SQL unterstützt JOINS, d.h. du kannst Tabellen im Query verknüpfen und musst keine zusätzliche Abfrage generieren.
    Es wird nur eine Abfrage an den MySQL Server gesendet, der diese dann verarbeitet. Was im Bezug auf die Abfragen letztendlich deinem Vorschlag gleichen würde. Der MySQL Server mag zwar etwas länger brauchen, um die erste Abfrage auszuführen, das sollte aber marginal sein.


    [...]
    Immerhin kommen noch die zusätzlichen Daten für die Tabellenstruktur dazu.
    Auch da weiß ich aber nicht, in wie weit sich das auswirkt bei der Gesammtgröße der Datenbank.

    Die Tabellenstruktur ist - theoretisch gesehen - sicherlich kein ausschlaggebendes Kriterium. ;-)



    Letzten Endes ist mir das aber egal...
    Ich schätze das der Effekt der einen oder anderen Lösung sehr minimal Ausfallen dürfte, da es sich hier ja nur um eine einfache Abfrage handelt.

    Bei großen Datenmengen und vor allem vielen gleichen Tags wird bei deiner Methode die Tabelle sehr redundant werden und somit auch langsamer als bei meiner Methode.

    Beitrag zuletzt geändert: 25.1.2010 20:55:35 von lucas9991
  22. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!