Schorsch: MySQL : Schwierige Suche

Guten Tag

Ich habe eine Tabelle "Titel" und eine Tabelle "Keywords".
Dazwischen liegt eine Verbindungstabelle.
Nun kann ich null oder mehrere Keywords einem Titel zuordnen.

Wie schaffe ich nun aber eine Abfrage, welche mir jeden Titel nur einmal, aber mit allen dazugehörigen Keywords ausgibt?

Versucht habe ich:

SELECT DISTINCT t.title_id, kj.keyw_id
FROM title AS t,
keyw_junc AS kj,
biblio_author AS a
WHERE t.title_id = kj.title_id

Aber die Titel mit mehreren Keywords werden mehrfach ausgegeben.

Gruss
Schorsch

  1. Hi,

    Aber die Titel mit mehreren Keywords werden mehrfach ausgegeben.

    dein Stichwort lautet GROUP BY

    MfG

    1. Salut

      dein Stichwort lautet GROUP BY

      Damit wird nur jeder Titel einmal ausgegeben.
      Soweit so gut.
      Aber es wird auch nur jeweils ein Keyword pro Titel ausgegeben. Ich bräuchte aber alle Keywords, die zu einem Titel gehören.

      Gruss
      Schorsch

  2. SELECT DISTINCT t.title_id, kj.keyw_id
    FROM title AS t,
    keyw_junc AS kj,
    biblio_author AS a
    WHERE t.title_id = kj.title_id

    das Zauberwort ist 'right outer join' zwischen den Tabellen. Und 'using (title_id)'

    1. Salut

      das Zauberwort ist 'right outer join' zwischen den Tabellen. Und 'using (title_id)'

      Nun habe ich:

      SELECT t.title_id, kj.keyw_id
      FROM title AS t
      RIGHT OUTER JOIN keyw_junc  AS kj
      using(title_id)

      Aber ich bekomme dieselben Titel mehrmals mit unterschiedelichen Keyworten.
      Erhalten sollte ich aber:
      Jeder Titel nur einmal mit den dazugehörigen Keyworten.

      Beispiel:

      Titel

      +----------+-------+
      | titel_id | titel |
      +----------+-------+
      |     1    | blah  |
      |------------------|
      |     2    | blah  |
      |------------------|

      Verbindungstabelle Titel > Keywords

      +-----------+--------------+-----------+
      |    id     |   titel_id   |  keyw_id  |
      +--------------------------------------+
      |    1      |      1       |     1     |
      |--------------------------------------|
      |    2      |      1       |     2     |
      |--------------------------------------|
      |    3      |      1       |     3     |
      |--------------------------------------|
      |    4      |      1       |     4     |
      +--------------------------------------+

      Gewünschtes Resultat:
      +-----------+---------+--------+-------+-------+
      | titel     |   keyw1 |  keyw2 | keyw3 | keyw4 |
      +-----------+---------+--------+-------+-------+
      |   blah    |    1    |    2   |   3   |   4   |
      +-----------+---------+--------+-------+-------+

      Ist das in einer MySQL-Abfrage überhaupt möglich?

      Gruss
      Schorsch

      1. Hallo,

        Gewünschtes Resultat:
        +-----------+---------+--------+-------+-------+
        | titel     |   keyw1 |  keyw2 | keyw3 | keyw4 |
        +-----------+---------+--------+-------+-------+
        |   blah    |    1    |    2   |   3   |   4   |
        +-----------+---------+--------+-------+-------+

        Ist das in einer MySQL-Abfrage überhaupt möglich?

        glaube ich kaum. Du müßtest ja alle Spalten ('keyw1', 'keyw2',...) erstmal im SELECT mit AS erstellen. Aber Du weißt ja gar nicht, wieviele Spalten es werden sollen. Da die Ergebnisse Datensatzweise sind hast Du das eine immer mehrfach.

        Du hast sicherlich eine Anwendung (PHP oder so). Da kannst Du die Ausgabe viel besser organisieren und auch wie oben.

        Gruß, Andreas

        --
        SELFFORUM - hier werden Sie geholfen,
        auch in Fragen zu richtiges Deutsch
        1. Hello,

          +-----------+---------+--------+-------+-------+
          | titel     |   keyw1 |  keyw2 | keyw3 | keyw4 |
          +-----------+---------+--------+-------+-------+
          |   blah    |    1    |    2   |   3   |   4   |
          +-----------+---------+--------+-------+-------+

          Ist das in einer MySQL-Abfrage überhaupt möglich?

          Nein. Eine "Denormalisierung" ist nicht mit einem SQL-Statement machbar.
          Wie soll eine Gruppenbildung ohne Wiederholung des Gruppierungskennzeichens möglich sein?
          Dies ist Aufgabe einer Schleife oder Rekursion.

          Man kann dies Problem unter Zuhilfenahme von if() und Uservariablen lösen.

          Dadurch enthält man dann Datansätze, wie sie im DataNorm-Format benutzt werden.

          Harzliche Grüße aus http://www.annerschbarrich.de

          Tom

          --
          Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
          Nur selber lernen macht schlau
          1. Salut

            Man kann dies Problem unter Zuhilfenahme von if() und Uservariablen lösen.

            Ich überlegte mir noch die Möglichkeit einer "Hilfstabelle". Eine vierte Tabelle neben den Tabellen "Title", "Keywords" und der "Title_Keywords_Junction" folgendes enthält:

            +--------+----------+--------------------------------------+
            |  id    | title_id |              keywords                |
            +--------+----------+--------------------------------------+
            |  1     |    1     | Keyword1, Keyword2, Keyword3, ...    |
            +----------------------------------------------------------+

            Damit, so überlegte ich mir, sind die Suchabfragen schneller, bequemer und das Resultat ist bereits das Gewünschte.

            Was hält Ihr davon?

            Was mir auch noch durch den Kopf geistert ist:
            Kommt es nicht oft vor, dass man 2 Tabellen + Verbindungstabelle hat und gerne alle Datensätze, aber keine Doppelt haben möchte?
            So wie in meinen Beispiel:
            Man möchte einen Titel, aber alle zu ihm gehörigen Keywords.
            Müsste nicht die Datenbank (in meinem Falle MySQL) so etwas händeln können?

            Gruss
            Schorsch

            1. +--------+----------+--------------------------------------+
              |  id    | title_id |              keywords                |
              +--------+----------+--------------------------------------+
              |  1     |    1     | Keyword1, Keyword2, Keyword3, ...    |
              +----------------------------------------------------------+
              Was hält Ihr davon?

              nichts. Dann hast Du doppelte Datenhaltung.

              Müsste nicht die Datenbank (in meinem Falle MySQL) so etwas händeln können?

              nö, wieso? die DB liefert Dir doch alle Informationen. Du willst nur eine Formatierte Ausgabe, das ist m.E. nicht die Aufgabe der DB. Warum machst du es nicht in Deiner Anwendung?

              Gruß, Andreas

              --
              SELFFORUM - hier werden Sie geholfen,
              auch in Fragen zu richtiges Deutsch
              1. Salut Andreas

                nö, wieso? die DB liefert Dir doch alle Informationen. Du willst nur eine Formatierte Ausgabe, das ist m.E. nicht die Aufgabe der DB. Warum machst du es nicht in Deiner Anwendung?

                Du schlägst also vor, ich soll eine Abfrage machen, zum Beispiel:

                SELECT t.title_id, t.title_title, kj.keyw_id
                FROM biblio_title AS t
                LEFT JOIN biblio_keyw_junc AS kj ON kj.title_id=t.title_id
                WHERE kj.keyw_id IS NOT NULL

                Und anschliessend lasse ich PHP die mehrfach vorkommenden "title_title" auf einen "title_title" schrumpfen, und teile ihm dann die entsprechenden keywords zu.

                Das geht so schon.
                Ich staune nur, dass die DB solche Dinge nicht ruck-zuck erledigen kann.

                Gruss
                Schorsch

                1. was habt Ihr denn alle mit diesem LEFT JOIN? Du willst doch die Titel _ohne_ Keywords gar nicht ausgeben oder?

                  SELECT title, keyword
                  FROM   titelTabelle, joinTabelle, keywordTabelle
                  WHERE  titelTabelle.id = joinTabelle.titel_id
                  AND    keywordTabelle.id = joinTabelle.keyword_id

                  ist jetzt ungetestet ;-), aber Du hattest ja eh schon eine funktionierende Abfrage, oder?

                  Und anschliessend lasse ich PHP die mehrfach vorkommenden "title_title" auf einen "title_title" schrumpfen, und teile ihm dann die entsprechenden keywords zu.

                  also "zuteilen" mußt Du doch gar nichts. Du mußt die Ergebnisliste doch eh in PHP einlesen, also kannst Du gleich in der Schleife sowas machen:

                  while( $datensatz=mysql_fetch_array($result) )
                  {
                     $ergebnis[$datensatz['title']][] = $datensatz['keyword']
                  }

                  dann kriegst du ein schönes zweidimensionales Array, in dem der Titel jeweils nur einmal vorkommt.

                  Gruß, Andreas

                  --
                  SELFFORUM - hier werden Sie geholfen,
                  auch in Fragen zu richtiges Deutsch
                  1. yo,

                    was habt Ihr denn alle mit diesem LEFT JOIN? Du willst doch die Titel _ohne_ Keywords gar nicht ausgeben oder?

                    <zitat>

                    Nun kann ich --> null <-- oder mehrere Keywords einem Titel zuordnen...

                    Wie schaffe ich nun aber eine Abfrage, welche mir --> jeden <-- Titel nur einmal, aber mit allen dazugehörigen Keywords ausgibt?

                    </zitat>

                    Ilja

                2. Hallo Schorsch

                  Das geht so schon.
                  Ich staune nur, dass die DB solche Dinge nicht ruck-zuck erledigen kann.

                  Wenn überhaupt, das DBMS (Datenbankmanagementsystem). Jet-SQL, das ist die DBMS-Engine hinter MS Access kann so etwas sogar:

                  TRANSFORM AggFunktion
                        Auswahlanweisung
                        PIVOT Pivot-Feld [IN (Wert1[, Wert2[, ...]])]

                  und für die Wertliste kannst Du ein SELECT-Statement verwenden ...

                  Das nennt sich in Access Kreuztabellenabfrage. Mir ist allerdings kein weiterer SQL-Dialekt bekannt, der Deine Anforderung unterstützt. Denn Andreas hat völlig Recht, das ist Sache der Anwendung und dort problemlos und ruckzuck erledigbar.

                  Freundliche Grüße

                  Vinzenz

                  1. Salut Vinzenz

                    Arbeit im Moment auf Mysql...

                    Gruss
                    Schorsch

    2. yo,

      das Zauberwort ist 'right outer join' zwischen den Tabellen. Und 'using (title_id)'

      ich würde eventuell einen LEFT OUTER JOIN nehmen.....

      Ilja

      1. das Zauberwort ist 'right outer join'
        ich würde eventuell einen LEFT OUTER JOIN nehmen.....

        ...oder vielleicht einen MIDDLE OUTER JOIN?... ;-)

        1. ...oder vielleicht einen MIDDLE OUTER JOIN?... ;-)

          wo hast du DEN denn gefunden.

          wenn du keinen blassen schimmer hast, gib hier bitte nicht solchen schwachsinn ab. das hilft niemandem weiter.

          1. wenn du keinen blassen schimmer hast, gib hier bitte nicht solchen schwachsinn ab.

            wie nett du bist! wenn man nach deinem argument ohne ahnung nichts ablassen darf: wann ziehst du deine untauglichen vorschläge zurück? wann klingelts bei dir?

            Ratefuchs

      2. ich würde eventuell einen LEFT OUTER JOIN nehmen.....

        ist mir beim 2. hinsehen auch aufgefallen.