Entwickler-Ecke
Sonstiges (Web-Entwicklung) - MySQL: Suche mit Stichwortverzeichnis
Yogu - Di 27.10.09 01:04
Titel: MySQL: Suche mit Stichwortverzeichnis
Hallo,
ich habe jetzt schon viele Google-Ergebnisse abgeklappert, finde aber leider keine Lösung. Vielleicht könnt ihr mir weiterhelfen:
Es existieren drei Tabellen, die für die Suche zuständig sind:
- search_items: Enthält die Artikel, die durchsucht werden können
- search_keywords: Enthält alle Stichwörter, die aus den Artikeln gesammelt wurden
- search_item_keyword:: Verknüpft Artikel mit Stichwörter, gibt also an, welche Stichwörter in welchem Artikel vorhanden sind.
Ich bin schon so weit, dass ich aus einer Suchanfrage (z.B. "Herbst Buch") Stichwörter herauslesen kann (Herbst|Herbstlich + Kochbuch|Buchhaltung). Ein Artikel muss also gefunden werden, wenn er z.B. "Herbst" und "Buchhaltung", oder auch "Herbstlich" und "Kochbuch" enthält. Oder-Verknüpfungen sind also innerhalb der Und-Verknüpfungen geschachtelt.
Jetzt dachte ich, ich könnte das Problem mittels Joins lösen:
SQL-Anweisung
1: 2: 3: 4: 5: 6: 7:
| SELECT * FROM search_items INNER JOIN search_item_keyword ON search_item_keyword.item_id = search_items.item_id AND (keyword_id = 'Herbst' OR keyword_id = 'Herbstlich') INNER JOIN search_item_keyword ON search_item_keyword.item_id = search_items.item_id AND (keyword_id = 'Kochbuch' OR keyword_id = 'Buchhaltung') |
(Die Werte für
keyword_id sind hier nur symbolisch zu verstehen.)
Dabei würde für jeden Artikel geprüft werden, ob es eine Verknüpfung mit einem der zur Auswahl stehenden Keywords gibt. Das klappt soweit auch ganz gut.
Wenn ein Artikel jetzt aber sowohl "Kochbuch" als auch "Buchhaltung" enthält, wird er zweimal aufgelistet. Das ist ein ernsthaftes Problem, denn um die Gesamtzahl der Treffer zu ermitteln muss die komplette Query in SQL formuliert werden und die Ergebnisse können nicht per PHP bearbeitet werden.
Jetzt meine Frage: Ist es möglich, Joins nur zur "Überprüfung, ob ein bestimmter Datensatz vorhanden ist" zu verwenden, ohne dabei für jeden gefundenen Datensatz eine Reihe im Ergebnis einzufügen?
Danke für eure Mühe!
Grüße,
Yogu
JüTho - Di 27.10.09 10:17
Hallo,
die Verbindung "Herbst" und "Herbstlich" schreit eigentlich nach einer LIKE-Abfrage; dann kannst du beide Prüfungen mit einem einzigen OR in einer einzigen JOIN-Tabelle zusammenziehen.
Vielleicht passt in dieser Situation auch eine Unterabfrage.
Mir ist bewusst, dass LIKE und Unterabfragen meistens (oft?) langsamer sind als JOINs; aber vielleicht wäre es dennoch sachgerechter.
Gruß Jürgen
jcp - Di 27.10.09 12:00
SQL-Anweisung
1: 2: 3: 4: 5: 6:
| SELECT COUNT(*) FROM search_items LEFT JOIN search_item_keyword ON search_item_keyword.item_id = search_items.item_id WHERE search_item_keyword.keyword_id = 'Buchhaltung' OR search_item_keyword.keyword_id = 'Herbst' |
Yogu - Di 27.10.09 16:49
JüTho hat folgendes geschrieben : |
die Verbindung "Herbst" und "Herbstlich" schreit eigentlich nach einer LIKE-Abfrage |
Diesen eindringlichen Aufruf habe selbst ich gehört; ich verwende ihn auch, um die keyword_id's zu ermitteln. Man kann aber auch mehrere Stichwörter per
Oder verknüpfen, was ich hier nicht geschrieben habe, da es ursprünglich nichts zur Sache tat.
JüTho hat folgendes geschrieben : |
Mir ist bewusst, dass LIKE[-Abfragen] meistens (oft?) langsamer sind als JOINs; aber vielleicht wäre es dennoch sachgerechter. |
Ich habe über 3000 Stichwörter in noch wenigen 369 Artikeln, die mehr als zwölf Tausend Artikel-Stichwort-Verknüpfungen haben. Die mit LIKE's zu durchsuchen wäre totale Zeitverschwendung und vom Server nicht tragbar.
jcp hat folgendes geschrieben : |
SQL-Anweisung 1: 2: 3: 4: 5: 6:
| SELECT COUNT(*) FROM search_items LEFT JOIN search_item_keyword ON search_item_keyword.item_id = search_items.item_id WHERE search_item_keyword.keyword_id = 'Buchhaltung' OR search_item_keyword.keyword_id = 'Herbst' | |
Danke für deine Antwort. Diese Query ergibt aber leider dasselbe Ergebnis wie die von mir gepostete (manche Artikel sind mehrfach vorhanden). Daher bringt mich die Lösung auch nicht weiter.
JüTho hat folgendes geschrieben : |
Vielleicht passt in dieser Situation auch eine Unterabfrage. |
Das ist es! :D
Ich habe bisher noch keine Unterabfragen verwendet, daher bin ich auch nicht selbst draufgekommen. Jetzt habe ich mich kurz in die Syntax eingearbeitet und eine Query zusammengebastelt, die endlich die Ergebnismenge liefert, die ich brauche. :)
SQL-Anweisung
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| SELECT * FROM search_items WHERE ( SELECT COUNT(search_item_keyword.item_id) FROM search_item_keyword WHERE search_item_keyword.item_id = search_items.item_id AND (keyword_id = 'Herbst' OR keyword_id = 'Herbstlich') ) > 0 AND ( SELECT COUNT(search_item_keyword.item_id) FROM search_item_keyword WHERE search_item_keyword.item_id = search_items.item_id AND (keyword_id = 'Kochbuch' OR keyword_id = 'Buchhaltung') ) > 0 |
Jetzt gibt's zwar für jedes Stichwort eine eigene Unterabfrage, aber damit kann ich leben.
Wenn jemand anderes Hilfe bei Suchen braucht, einfach bei mir melden - meine Suche klappt inzwischen wunderbar. Danke,
JüTho! :D
Grüße,
Yogu
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!