Autor Beitrag
Yogu
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2598
Erhaltene Danke: 156

Ubuntu 13.04, Win 7
C# (VS 2013)
BeitragVerfasst: Di 27.10.09 01:04 
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:

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2021
Erhaltene Danke: 6

Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
BeitragVerfasst: 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

Für diesen Beitrag haben gedankt: Yogu
jcp
Hält's aus hier
Beiträge: 6



BeitragVerfasst: Di 27.10.09 12:00 
ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2598
Erhaltene Danke: 156

Ubuntu 13.04, Win 7
C# (VS 2013)
BeitragVerfasst: Di 27.10.09 16:49 
user profile iconJüTho hat folgendes geschrieben Zum zitierten Posting springen:
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.

user profile iconJüTho hat folgendes geschrieben Zum zitierten Posting springen:
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.

user profile iconjcp hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden 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.

user profile iconJüTho hat folgendes geschrieben Zum zitierten Posting springen:
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. :)

ausblenden 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, user profile iconJüTho! :D

Grüße,
Yogu