werbeklaus: Suche nach mehreren Einträgen in SET

Hallo,
ich habe eine MySQL-Tabelle, in der die Fotos einer Bildergallerie eingetragen sind. Eine der Spalten ist vom Typ SET, in die eingetragen ist, welche Personen auf dem Bild zu sehen sind.

Besuchern der Homepage möchte ich nun möglich machen, sich alle Bilder anzuschauen, auf denen person2 und person4 zu sehen ist.

In Dokumentation zu SET finde ich nur die Möglichkeit, nach _einem_ Wert zu suchen (Mithilfe von FIND_IN_SET()).

In der Funktionsliste taucht diese Funktion jedoch nicht auf, sodass ich nicht weiss, ob ich denn auch mehrere needles übergeben kann.

Eine Möglichkeit wäre natürlich, mit einer Schleife den SQL-Befehl so zu generieren, dass nach
FIND_IN_SET('person2','Personen') AND FIND_IN_SET('person4','Personen')
gesucht wird, was aber mE unsauber ist und auch PHP sowie MySQL mehr belasten dürfte.

Vielen Dank für Hilfe,
werbeklaus

  1. Hallo,

    erstens sollte man in SET keine rein numerischen Indexe als Argumente verwenden. Das gibt Kuddelmuddel. MySQL ist da mackig!

    Außerdem frage ich mich, was hier der Untertyp SET mit seinem begrenzten Wetevorrat zu uschen hat.

    Und dann gibt es immer noch "Find in Set". Must Du im MySQL-Manual mal nach suchen.

    LG
    Chris

    1. Hallo,

      erstens sollte man in SET keine rein numerischen Indexe als Argumente verwenden. Das gibt Kuddelmuddel. MySQL ist da mackig!

      Das versteh ich schon nicht. Ich habe doch keine rein numerischen Indexe !??!? Oder war das eine vorsorgliche Warnung?

      Außerdem frage ich mich, was hier der Untertyp SET mit seinem begrenzten Wetevorrat zu uschen hat.

      Es handelt sich um eine Homepage über meine Eltern, meine Geschwister und deren Freunde/innen und mich.
      Diese 9 Personen scheinen mir in einem SET-Datentyp gut aufgehoben, weil sie ja ein sehr "begrenzten Wertevorrat" darstellen.

      Und dann gibt es immer noch "Find in Set". Must Du im MySQL-Manual mal nach suchen.

      Vielleicht hatte ich nicht deutlich genug gesagt, dass die Funktion in in keiner Funktionsliste zu finden ist _und_ auch nicht von der Suche gefunden wird.

      werbeklaus

      1. Hallo,

        erstens sollte man in SET keine rein numerischen Indexe als Argumente verwenden. Das gibt Kuddelmuddel. MySQL ist da mackig!

        Das versteh ich schon nicht. Ich habe doch keine rein numerischen Indexe !??!? Oder war das eine vorsorgliche Warnung?

        Das war vorsorglich. Wenn nämlich das numerische Argument nicht gefunden werden kann, wird als nächstes im Index gesucht. Und die Wahrscheinlichkeit, dass MySQL dort fündig wird, ist recht hoch. Leider stimmt der Index eines Wertes mit dem Wert selten überein :-(

        Außerdem frage ich mich, was hier der Untertyp SET mit seinem begrenzten Wetevorrat zu uschen hat.

        Es handelt sich um eine Homepage über meine Eltern, meine Geschwister und deren Freunde/innen und mich.
        Diese 9 Personen scheinen mir in einem SET-Datentyp gut aufgehoben, weil sie ja ein sehr "begrenzten Wertevorrat" darstellen.

        Das mag zwar praktisch derzeit noch "begrenzt" sein, aber theoretisch ist diese Relation unbegrenzt. Es wäre durchaus vorstellbar, dass Du die entstehende Software auch auf andere Bereiche (Deinen Sportverein, Gruppe der korrupten Politiker) übertragen möchtest. Und diese beiden sind mMn keinesfalls mit SET abdeckbar.

        Und dann gibt es immer noch "Find in Set". Must Du im MySQL-Manual mal nach suchen.

        Vielleicht hatte ich nicht deutlich genug gesagt, dass die Funktion in in keiner Funktionsliste zu finden ist _und_ auch nicht von der Suche gefunden wird.

        Ok, ich arbeite nochmal kostenlos für Dich: :-))

        http://dev.mysql.com/doc/refman/4.0/de/set.html

        LG
        Chris

        1. Hallo,

          Das mag zwar praktisch derzeit noch "begrenzt" sein, aber theoretisch ist diese Relation unbegrenzt. Es wäre durchaus vorstellbar, dass Du die entstehende Software auch auf andere Bereiche (Deinen Sportverein, Gruppe der korrupten Politiker) übertragen möchtest. Und diese beiden sind mMn keinesfalls mit SET abdeckbar.

          Nungut, zurzeit finde ich es mit Abstand das einfachste.

          Ok, ich arbeite nochmal kostenlos für Dich: :-))

          Danke !

          http://dev.mysql.com/doc/refman/4.0/de/set.html

          Ich versteh nicht... Übersehe ich dort etwas? Diese Seite hatte ich doch (in Englisch) schon angegeben. Und dort ist zwar FIND_IN_SET erwähnt, jedoch ist dort keine Möglichkeit beschrieben, wie ich nach mehreren personen suchen kann....

          Aber vllt werde ich doch einfach die AND-Konstruktion verwenden....

          werbeklaus

          1. Hallo,

            Aber vllt werde ich doch einfach die AND-Konstruktion verwenden....

            mysql> SELECT * FROM tabelle WHERE set_spalte = 'wert1,wert2';

            Wer lesen kann, ist klar im Vorteil :-)

            Übrigens, wer sehender Weise und nur aus Faulheit wider besseren Wissens auf den Abgrund zusteuert, kann meinetwegen auch ruhig hinunterstürzen. Solltest Du also demnächst nochmal Fragen zum Thema Datenmodellierung haben, stehen die auf meiner Blackkist.

            LG
            Chris

            1. Hallo,

              mysql> SELECT * FROM tabelle WHERE set_spalte = 'wert1,wert2';

              Aber gilt das denn auch, wenn ich nach
              'wert1,wert3'
              suche, in der Zelle jedoch
              'wert1,wert2,wert3'
              steht?

              Solltest Du also demnächst nochmal Fragen zum Thema Datenmodellierung haben, stehen die auf meiner Blackkist.

              Na vielen Dank.

              werbeklaus

      2. Moin!

        Es handelt sich um eine Homepage über meine Eltern, meine Geschwister und deren Freunde/innen und mich.
        Diese 9 Personen scheinen mir in einem SET-Datentyp gut aufgehoben, weil sie ja ein sehr "begrenzten Wertevorrat" darstellen.

        Auch diese eng begrenzte Gruppe an Personen kann auf biologische oder rechtliche Weise Veränderungen unterworfen sein. Der Tod hat hierbei datenbanktechnisch natürlich keine Auswirkungen, denn die bestehenden Fotos der Person existieren noch.

        Aber interessant ist das Hinzukommen neuer Personen. Sei es durch Geburt, neue Lebensabschnittspartner oder gar Heirat (der evtl. eine Scheidung vorausging).

        All diese Veränderungen müssen in der Datenbank durch Veränderung der Tabellendefinition implementiert werden - und das ist ganz ganz schlechtes Datenbankdesign. Denn oberste Prämisse ist, dass sich an der Tabellendefinition im Betrieb nichts ändern darf. Alles, was variabel ist, ist als Daten zu behandeln und in entsprechenden Tabellen abzulegen.

        Beschäftige dich mit Joins. Du hast zwei Datentabellen, Fotos und Personen, und eine weitere, in der die Verknüpfung von Foto-ID und Personen-ID abgelegt wird (n:m-Relation), ein Foto kann mehrere Personen enthalten, und eine Person kann auf mehreren Fotos auftauchen.

        - Sven Rautenberg

        --
        My sssignature, my preciousssss!
        1. Hallo,

          Auch diese eng begrenzte Gruppe an Personen kann auf biologische oder rechtliche Weise Veränderungen unterworfen sein.
          Aber interessant ist das Hinzukommen neuer Personen. Sei es durch Geburt, neue Lebensabschnittspartner oder gar Heirat (der evtl. eine Scheidung vorausging).

          Okay, das Stimmt natürlich. Aber kann ich denn nicht einfach einen 10. Wert hinzukommen lassen, und schon ist für das _hinzukommen_ gesorgt? Und ein herausfallen könnte man zur Not einfach mit dem rauslöschen aller Vorkomnisse realisieren.
          Nun gut, dass das schlechter Stil ist, sehe ich ein.

          Beschäftige dich mit Joins. Du hast zwei Datentabellen, Fotos und Personen, und eine weitere, in der die Verknüpfung von Foto-ID und Personen-ID abgelegt wird (n:m-Relation), ein Foto kann mehrere Personen enthalten, und eine Person kann auf mehreren Fotos auftauchen.

          Das heisst, in der Relations-Tabelle steht sozusagen

          Foto-ID | Person-ID
          1 | 2
          1 | 3
          1 | 4
          2 | 2
          ....

          Wenn ich das so verstanden habe und ihr das für besser haltet (ich kann das grad noch nicht so abschätzen), werde ich das wohl noch ändern. Denn im Nachhinein die Datenstruktur ändern kann sehr sehr böse werden.

          werbeklaus

          1. Hallo,

            das Herauslöschen wird die größten Probleme bereiten. Wie wird denn wohl eine refrenz auf dieses Feld aussehen? Na klar: über den Index.
            Wenn Du nun aber ein Element rauslöschst, werden die Indexe neu vergeben und die Referenzen stimmen nicht mehr.

            SET und ENUM eignen sich nur für schächstens wachsende Systeme, aber keinesfalls für dynamische.

            LG
            Chris

          2. Moin!

            Aber interessant ist das Hinzukommen neuer Personen. Sei es durch Geburt, neue Lebensabschnittspartner oder gar Heirat (der evtl. eine Scheidung vorausging).
            Okay, das Stimmt natürlich. Aber kann ich denn nicht einfach einen 10. Wert hinzukommen lassen, und schon ist für das _hinzukommen_ gesorgt? Und ein herausfallen könnte man zur Not einfach mit dem rauslöschen aller Vorkomnisse realisieren.

            Angenommen, einer der bisherigen 9 Personen heiratet eine Großfamilie an. Also gibt es als zusätzliche Personen:
            1. Den neuen Ehepartner
            2. Vater des Ehepartners
            3. Mutter des Ehepartners
            4.-7. Vier Großeltern des Ehepartners
            8.-10. drei Geschwister des Ehepartners
            11.-13. drei Ehepartner der Geschwister
            14.-19. je zwei Kinder der Geschwisterehen
            20. ein Kind des Ehepartners aus einer vorigen Beziehung
            21. zum Kind den anderen Elternteil.
            22. die beste Freundin des Ehepartners
            23. den besten Freund des Kindes

            Und schon hast du spontan 32 Personen, und damit das Fassungsvermögen von SET ausgeschöpft. Wehe, aus der Ehe entsteht dann noch ein Kind!

            Nun gut, dass das schlechter Stil ist, sehe ich ein.

            Das ist gut.

            Das heisst, in der Relations-Tabelle steht sozusagen

            Foto-ID | Person-ID
            1 | 2
            1 | 3
            1 | 4
            2 | 2
            ....

            Wenn ich das so verstanden habe und ihr das für besser haltet (ich kann das grad noch nicht so abschätzen), werde ich das wohl noch ändern. Denn im Nachhinein die Datenstruktur ändern kann sehr sehr böse werden.

            Richtig verstanden.

            - Sven Rautenberg

            --
            My sssignature, my preciousssss!
            1. Hallo,

              ...
              Und schon hast du spontan 32 Personen, und damit das Fassungsvermögen von SET ausgeschöpft. Wehe, aus der Ehe entsteht dann noch ein Kind!

              Ein bisschen Konstruiertes Beispiel, oder nicht ;-)

              Das heisst, in der Relations-Tabelle steht sozusagen

              Foto-ID | Person-ID
              1 | 2
              1 | 3
              1 | 4
              2 | 2
              ....

              Richtig verstanden.

              Okay. Nun kann ich einfache Joins zwar machen, relatic bald stoße ich aber an meine Grenzen.
              Wenn ich nun nach allen Bildern suchen will, die Person1 und person3 enthalten, dann muss ich nachschlagen, für welche Foto-ID die Zeilen mit person-id 1 und 3 vorkommen, und zu diesem Foto die entsprechende Zeile der Fotos suchen.
              Wie mach das?
              Ich sehe da leider keinen Lösungsansatz ....

              werbeklaus

              1. Moin!

                Und schon hast du spontan 32 Personen, und damit das Fassungsvermögen von SET ausgeschöpft. Wehe, aus der Ehe entsteht dann noch ein Kind!
                Ein bisschen Konstruiertes Beispiel, oder nicht ;-)

                Glaube ich nicht. Vielleicht ist etwas zuviel Verwandschaft im Spiel, dann ersetze einfach einige Geschwister und Kinder durch gute Freunde und Bekannte des neuen Ehepartners.

                Oder stell' dir einfach vor, ein Schulkind ist unter den 9 Personen, und es soll ein Klassenfoto in deine DB aufgenommen werden. Dann hast du auf einen Schlag eine Klassenstärke von mindestens 20 Kindern zu verarbeiten.

                Selbst wenn du in DEINEM Leben mit den maximal möglichen 32 Elementen in SET auskommst - wenn deine Kinder die Datenbank weiterführen, kommen die eben in Probleme, weil die Verwandtschaft und Bekannschaft stetig anwächst, alte SET-Ids aber nicht wiederbenutzt werden dürfen.

                Okay. Nun kann ich einfache Joins zwar machen, relatic bald stoße ich aber an meine Grenzen.
                Wenn ich nun nach allen Bildern suchen will, die Person1 und person3 enthalten, dann muss ich nachschlagen, für welche Foto-ID die Zeilen mit person-id 1 und 3 vorkommen, und zu diesem Foto die entsprechende Zeile der Fotos suchen.

                SELECT foto.fotodaten, joiner.foto-id, joiner.person-id FROM fototabelle as foto, foto-person-tabelle as joiner WHERE foto.foto-id = joiner.foto-id AND joiner.person-id IN (2,4) ORDER BY whatever LIMIT irgendwas

                Die IDs der zu suchenden Personen kriegst du raus, wenn du den Benutzer in einer passenden Suchmaske nett fragst und als Antwort die IDs einsammelst (z.B. select multiple mit value-Attribut = id und Personenname als selektierbare Anzeige).

                - Sven Rautenberg

                --
                My sssignature, my preciousssss!
                1. Hallo,

                  Glaube ich nicht.

                  Ist ja okay, Veränderung kann es trotzdem geben ;-)

                  Oder stell' dir einfach vor, ein Schulkind ist unter den 9 Personen, und es soll ein Klassenfoto in deine DB aufgenommen werden. Dann hast du auf einen Schlag eine Klassenstärke von mindestens 20 Kindern zu verarbeiten.

                  Es werden ja nicht alle Personen auf Fotos aufgenommen, denn ein Besucher der Homepage wird vorrangig nach einer dieser (zur Zeit 9 ;-) Personen suchen.

                  SELECT foto.fotodaten, joiner.foto-id, joiner.person-id FROM fototabelle as foto, foto-person-tabelle as joiner WHERE foto.foto-id = joiner.foto-id AND joiner.person-id IN (2,4) ORDER BY whatever LIMIT irgendwas

                  Danke dir.

                  Die IDs der zu suchenden Personen kriegst du raus, wenn du den Benutzer in einer passenden Suchmaske nett fragst und als Antwort die IDs einsammelst (z.B. select multiple mit value-Attribut = id und Personenname als selektierbare Anzeige).

                  Hatt ich so schon vor. Das Select kann ja aus der Personen-Tabelle generiert werden.

                  werbeklaus