Jeena Paradies: MySQL Suche über mehrere Tabellen

Hallo,

Ich habe eine Voltextsuche mit mysql gebastelt so wie es hier beschrieben ist: http://www.dclp-faq.de/q/q-mysql-volltextsuche.html

Das funktioniert auch wunderbar aber ich möchte mehr. Bisher durchsuche ich nur eine von drei Tabellen, nur die news Tabelle. Ich möchte aber noch die comments Tabelle und die content Tabelle gleichzeitig durchsuchen lassen.

Ich verstehe aber leider nicht wirklich wie ich das machen soll, vor allem verstehe ich nicht wie ich dann aus den Ergebnissen herausfinden kann in welcher Tabelle es gefunden wurde. Ich muss da je nach Tabelle einen anderen Link generieren. Einmal /news/X für die News, dann /news/X#cXX für die Kommentare die auf den Newsseiten sind und dann noch aus dem Content /XXXXX wobei die X Variablen für verschiedene IDs aus der Datenbank sind.

Grüße
Jeena Paradies

--
Logo drucken welches sich auf einer dunklen Seite befindet
http://jeenaparadies.de/weblog/2004/august/print-logo/
Spammer jetzt beim Arbeitsamt
http://jeenaparadies.de/artikel/arbeitsamt-spammer/
  1. Hallo Jeena!

    [Suche über drei verschiedene Tabellen]

    Warum machst du nicht einfach drei SQL-Abfragen bzw. drei Selects -- für jede Tabelle eine? Pro Tabelle bzw. Kategorie gibtst du jeweils die -- sagen wir die ersten zehn -- Ergebnisse aus. Ein "Weiter Ergebnisse"-Link könnte dann alle Ergebnisse pro Tabelle bzw. Kategorie liefern.

    Du könntest dein Such-Formular auch dementsprechend erweitern, dass du Checkboxen pro Tabelle bzw. Kategorie ausgibst, mit denen der Besucher die Bereiche auswählen kann, in denen gesucht werden soll.

    Grüsse,

    Sky

    1. Hallo,

      Warum machst du nicht einfach drei SQL-Abfragen bzw. drei Selects -- für jede Tabelle eine? Pro Tabelle bzw. Kategorie gibtst du jeweils die -- sagen wir die ersten zehn -- Ergebnisse aus. Ein "Weiter Ergebnisse"-Link könnte dann alle Ergebnisse pro Tabelle bzw. Kategorie liefern.

      Drei SQL abfragen? Aber dann ist doch der Sinn der MySQL suche schon wieder futsch, denn die Ergebnisse werden nicht einheitlich nach der Relevanz sortiert, sondern je tabelle nach der relevanz. Das ist aber nicht das was ich wollte. Oder verstehe ich dich irgendwie falsch?

      Du könntest dein Such-Formular auch dementsprechend erweitern, dass du Checkboxen pro Tabelle bzw. Kategorie ausgibst, mit denen der Besucher die Bereiche auswählen kann, in denen gesucht werden soll.

      Das mache ich eventuell, aber der content Bereich ist so klein (6 Seiten) dass es nicht nicht wirklich lohnt da noch einen extra button dafür zu machen. Dennoch sollen sie gefunden werden wenn nach ihnen gesucht wird.

      Grüße
      Jeena Paradies

      --
      Logo drucken welches sich auf einer dunklen Seite befindet
      http://jeenaparadies.de/weblog/2004/august/print-logo/
      Spammer jetzt beim Arbeitsamt
      http://jeenaparadies.de/artikel/arbeitsamt-spammer/
  2. Hi,

    nur mal so ein Tip, mach doch ein Union Select über die Tabellen.
    Und benutze für jede UNION-Tabelle ein Feld zur Identifikation:

    SELECT
     [combinedTables].[felda]
     ,[combinedTables].[feldb]  -- -> text feld zum durchsuchen
     ,[combinedTables].[feldc]  -- -> tabellen identifier
    FROM
     (SELECT ID as [felda], text as [feldb], 'tab1' as [feldc] FROM tab1
      UNION
      SELECT ID as [felda], text as [feldb], 'tab2' as [feldc] FROM tab2
      UNION
      SELECT ID as [felda], text as [feldb], 'tab1' as [feldc] FROM tab3)
     as [combinedTables]
    WHERE MATCH [combinedTables].[feldb] AGAINST ('wort1 wort2')

    so ungefähr könnte ich mir das vorstellen ;-)

    Ciao, Frank

    1. Hallo,

      nur mal so ein Tip, mach doch ein Union Select über die Tabellen.

      Schade das wird wohl nicht funktionieren denn ich habe MySQL 3.23.56 und UNION ist implementiert in MySQL 4.0.0.

      Trotzdem danke für deine Idee. Falls dir noch was einfält immer her damit.

      Grüße
      Jeena Paradies

      --
      Logo drucken welches sich auf einer dunklen Seite befindet
      http://jeenaparadies.de/weblog/2004/august/print-logo/
      Spammer jetzt beim Arbeitsamt
      http://jeenaparadies.de/artikel/arbeitsamt-spammer/
      1. Was spricht gegen ein Update? 4.0.20 ist stabil und "generally available".
        Der Yeti

        1. Hallo,

          Was spricht gegen ein Update? 4.0.20 ist stabil und "generally available".

          mein Provider :/

          Grüße
          Jeena Paradies

          --
          Logo drucken welches sich auf einer dunklen Seite befindet
          http://jeenaparadies.de/weblog/2004/august/print-logo/
          Spammer jetzt beim Arbeitsamt
          http://jeenaparadies.de/artikel/arbeitsamt-spammer/
          1. Na dann sollte man mal ein bisschen auf den Putz klopfen. ;-)
            Schließlich kann Gigatrack seinen Usern doch nicht zumuten mit alten Versionen zu arbeiten.

            1. Hallo,

              Na dann sollte man mal ein bisschen auf den Putz klopfen. ;-)

              Das tue ich schon ;)

              Schließlich kann Gigatrack seinen Usern doch nicht zumuten mit alten Versionen zu arbeiten.

              Gigatrack?

              Grüße
              Jeena Paradies

              --
              Logo drucken welches sich auf einer dunklen Seite befindet
              http://jeenaparadies.de/weblog/2004/august/print-logo/
              Spammer jetzt beim Arbeitsamt
              http://jeenaparadies.de/artikel/arbeitsamt-spammer/
              1. Gigatrack?

                Als Tech-C und Zone-C von jeenaparadies.de steht Gigatrack. Aber das heißt natürlich nix, der Server kann ja woanders stehen.

                Der Yeti

                --
                Habe nun, ach! WInfo, BWL, und Mathe, Und leider auch Info!
                Durchaus studiert, mit heißem Bemühn. Da steh' ich nun, ich armer Thor!
                Und bin so klug als wie zuvor!
                1. Hallo,

                  Als Tech-C und Zone-C von jeenaparadies.de steht Gigatrack. Aber das heißt natürlich nix, der Server kann ja woanders stehen.

                  Ach so, hm das ist nur die blöde Umleitung, die ich im November anders lösen werde. Der Server steht in Österreich.

                  Grüße
                  Jeena Paradies

                  --
                  Logo drucken welches sich auf einer dunklen Seite befindet
                  http://jeenaparadies.de/weblog/2004/august/print-logo/
                  Spammer jetzt beim Arbeitsamt
                  http://jeenaparadies.de/artikel/arbeitsamt-spammer/
  3. Hallo,

    Also leider ist das wohl nicht so einfach wie ich dachte. Ich kenn mich ja nicht aus, aber kann ich da nicht irgendwie irgendetwas machen damit das möglich ist mit dieser Version von MySQL?

    Grüße
    Jeena Paradies

    --
    Logo drucken welches sich auf einer dunklen Seite befindet
    http://jeenaparadies.de/weblog/2004/august/print-logo/
    Spammer jetzt beim Arbeitsamt
    http://jeenaparadies.de/artikel/arbeitsamt-spammer/
    1. hi,

      Also leider ist das wohl nicht so einfach wie ich dachte. Ich kenn mich ja nicht aus, aber kann ich da nicht irgendwie irgendetwas machen damit das möglich ist mit dieser Version von MySQL?

      ich würde sagen, nein.

      bliebe also wohl nur noch, drei einzelne abfragen, je tabelle, zu machen, und diese dann nachher im verarbeitenden script auf ihre relevanz zu prüfen und danach sortiert "ineinander zu mischen".

      wenn du dir http://dev.mysql.com/doc/mysql/de/Fulltext_Search.html mal anschaust, siehst du da im zweiten beispiel, wie man sich den "ordnungswert" der relevanz auch mit ausgeben lassen kann, wenn man MATCH ... AGAINST nicht nur in der WHERE-klausel anwendet, sondern auch als "spalte" angibt, die zurückgeliefert werden soll.

      mysql> SELECT id,MATCH (titel,artikeltext) AGAINST ('Tutorial') FROM artikel;
      +----+------------------------------------------------+
      | id | MATCH (titel,artikeltext) AGAINST ('Tutorial') |
      +----+------------------------------------------------+
      |  1 |                               0.64840710366884 |
      |  2 |                                              0 |
      |  3 |                               0.66266459031789 |
      |  4 |                                              0 |
      |  5 |                                              0 |
      |  6 |                                              0 |
      +----+------------------------------------------------+

      diese zahlen sind also das sortierkriterium für die relevanz.

      wenn du jetzt aus allen drei tabellen so ausliest, dass du diesen wert ebenfalls im ergebnis mitgeliefert bekommst, könntest du dir alle drei abfrageergebnisse in arrays packen.

      und beim ausgeben gehst du dann wie folgt vor:

      eine schleife, die so lange läuft, wie mindestens zwei der arrays noch ein element besitzt.

      in dieser schleife holst du dir dann aus allen arrays, die noch elemente besitzen, das element mit dem jeweils höchsten sortier-wert, und schaust nach, welcher von diesen werten wiederum der höchste ist. dieses element wird dann ausgegeben, und anschliessend mit unset() aus seinem array entfernt.

      na und das ziehst du jetzt so lange durch, wie es noch in mindestens zwei der arrays werte gibt.

      wenn es nachher nur noch in einem der arrays elemente gibt, werden diese dann anschliessend auch noch sortiert ausgegeben.

      (oder fällt jemandem ein, wie man das mit einem zusammenführen der drei einzel-arrays zu einem mittels array_merge und anschliessendem sortieren nach dem sortierkriterium auch einfacher machen könnte?)

      gruß,
      wahsaga

      --
      "Look, that's why there's rules, understand? So that you _think_ before you break 'em."
      1. hi,

        ich muss noch ergänzen:

        das kann natürlich nur klappen, wenn mysql die "relevanz" irgendwie allgemein berechnet, und _nicht_ auf den speziellen datenbestand der jeweiligen tabelle bezogen.

        weiß da jemand genaueres?

        gruß,
        wahsaga

        --
        "Look, that's why there's rules, understand? So that you _think_ before you break 'em."
        1. Hallo,

          das kann natürlich nur klappen, wenn mysql die "relevanz" irgendwie allgemein berechnet, und _nicht_ auf den speziellen datenbestand der jeweiligen tabelle bezogen.
          weiß da jemand genaueres?

          ------------------------
          Jedes korrekte Wort in der Textsammlung und in der Anfrage wird nach seiner Signifikanz in der Anfrage oder der Textsammlung gewichtet. Daher hat ein Wort, dass in vielen Dokumenten vorkommt, ein geringeres Gewicht (und kann sogar 0 Gewicht haben), weil es in dieser bestimmten Textsammlung einen geringen semantischen Wert hat. Ansonsten, wenn das Wort selten vorkommt, erhält es ein höheres Gewicht. Die Gewichte der Wörter werden anschließend kombiniert, um die Relevanz der Zeile zu berechnen.
          ------------------------

          Dann ist das wohl auch nicht das wahre. Hier wird wirklich nur - wie brfürchtet - mit der einen Tabelle gearbeitet. Und wir waren schon so nah dran.

          Grüße
          Jeena Paradies

          --
          Logo drucken welches sich auf einer dunklen Seite befindet
          http://jeenaparadies.de/weblog/2004/august/print-logo/
          Spammer jetzt beim Arbeitsamt
          http://jeenaparadies.de/artikel/arbeitsamt-spammer/
      2. Hallo,

        Vielen Dank schon mal für deine Hilfe. Das hat mich auf jeden Fall viel weiter gebracht.

        (oder fällt jemandem ein, wie man das mit einem zusammenführen der drei einzel-arrays zu einem mittels array_merge und anschliessendem sortieren nach dem sortierkriterium auch einfacher machen könnte?)

        Guck dir mal hier ganz unten das zweitletzte Beispiel an http://de.php.net/array_multisort das ist doch das was ich brauche um mit deinem Beipiel voranzukommen oder nicht?

        Grüße
        Jeena Paradies

        --
        Logo drucken welches sich auf einer dunklen Seite befindet
        http://jeenaparadies.de/weblog/2004/august/print-logo/
        Spammer jetzt beim Arbeitsamt
        http://jeenaparadies.de/artikel/arbeitsamt-spammer/
        1. hi,

          Guck dir mal hier ganz unten das zweitletzte Beispiel an http://de.php.net/array_multisort das ist doch das was ich brauche um mit deinem Beipiel voranzukommen oder nicht?

          ja, wäre eine möglichkeit gewesen.
          mein ansatz war auf jeden fall viel zu kompliziert.

          man hätte auch genausogut alle datensätze in ein array packen können, und dieses dann mit usort() und einer kleinen eigendefinierten vergleichsfunktion sortieren können.

          aber da das mit der relevanz ja eh nicht so hinzuhauen scheint (dein posting https://forum.selfhtml.org/?t=88227&m=526130), auch egal :-/

          gruß,
          wahsaga

          --
          "Look, that's why there's rules, understand? So that you _think_ before you break 'em."
  4. Hallo,

    Hallo,

    Ich habe eine Voltextsuche mit mysql gebastelt so wie es hier beschrieben ist: http://www.dclp-faq.de/q/q-mysql-volltextsuche.html

    Das funktioniert auch wunderbar aber ich möchte mehr. Bisher durchsuche ich nur eine von drei Tabellen, nur die news Tabelle. Ich möchte aber noch die comments Tabelle und die content Tabelle gleichzeitig durchsuchen lassen.

    vieleicht hilft Dir die folgende Idee weiter.
    CREATE TEMPORARY TABLE tabelle [(create_definition,...)]
    [tabellen_optionen] [select_statement]

    Dann mit den zwei anderen zu durchsuchenden Tabellen jeweils
    INSERT [INTO] tabelle [(spalten_liste)] SELECT ...

    Die select statements beinhalten jeweils alle nötigen match funktionen und die vollständigen Texte, die Gewichtung ist irrelevant. Die Ursprungstabellen solltest Du vieleicht als Referenz mit einfügen.
    Auf diese Tabelle implementierst Du dann Deine gewünschte Volltextsuche. Damit hast Du die Gewichtung der Suche tabellenübergreifend implementiert. Die Frage ist natürlich, ob das auch performant genug ist.
    Wenn die Seite mit den Suchergebnissen keine Blätter-Funktion enthält, kannst Du die temporäre Tabelle sofort wieder löschen, nachdem der HTML content generiert ist.

    Grüße
    Jeena Paradies

    tschau,
    ziegenmelker