Suche im Kategoriebaum

Suche im Kategoriebaum

am 13.07.2005 13:54:20 von skanto

Hallo,

ich muss eine Suche realisieren, die sich über mehrere Felder/Tabellen
erstreckt. Auf den ersten Blick eigentlich kein großes Problem. Meine
Suche sieht momentan etwa so aus:
Sei der Suchbegriff "a b"

SELECT * FROM datensaetze WHERE
CONCAT_WS(name, beschreibung, hersteller, kategorie) LIKE '%a%' AND
CONCAT_WS(name, beschreibung, hersteller, kategorie) LIKE '%b%' ...

Ich verwende folgende Tabellenstruktur und hole mir Hersteller- und
Kategorienamen über LEFT JOINs:

datensaetze:
id, name, beschreibung, hersteller, kategorie, ...

kategorien:
id, name, parent

Die Kategorietabelle sieht in etwa so aus:
id name parent
1 | Sport | 0
2 | Spiel | 0
3 | Basketball | 1

Wenn ich nun nach "Sport" suche, werden natürlich keine Datensätze
gefunden, die in der Untergruppe Basketball sind. Kann mir jemand einen
Hinweis geben, wie ich das Problem lösen kann?

Manuel

Re: Suche im Kategoriebaum

am 16.07.2005 14:18:57 von Uli Honal

Manuel Wohlers wrote:

> ich muss eine Suche realisieren, die sich über mehrere Felder/Tabellen
> erstreckt. [..] Suchbegriff "a b"
>
> SELECT * FROM datensaetze WHERE

16.14. Warum soll ich nicht SELECT * schreiben?
http://www.php-faq.de/q/q-sql-select.html

> CONCAT_WS(name, beschreibung, hersteller, kategorie) LIKE '%a%' AND
> CONCAT_WS(name, beschreibung, hersteller, kategorie) LIKE '%b%' ...

Sieht aus, als würde es funktionieren. Aber Deine Datenbank kann keinen
Index verwenden, bei einer grossen Datenmenge würde das spürbar langsam
werden.

> Ich verwende folgende Tabellenstruktur und hole mir Hersteller- und
> Kategorienamen über LEFT JOINs:
>
> datensaetze:
> id, name, beschreibung, hersteller, kategorie, ...
>
> kategorien:
> id, name, parent

Fein. Nur die Tabellennamen solltest Du nochmal überdenken. Mein
Vorschlag wäre 'produkt' und 'kategorie', falls es sich um einen Shop
handelt.

Das Feld datensaetze.kategorie enthält eine ID, nehme ich an?

> Die Kategorietabelle sieht in etwa so aus:
> id name parent
> 1 | Sport | 0
> 2 | Spiel | 0
> 3 | Basketball | 1
>
> Wenn ich nun nach "Sport" suche, werden natürlich keine Datensätze
> gefunden, die in der Untergruppe Basketball sind. Kann mir jemand einen
> Hinweis geben, wie ich das Problem lösen kann?

Du müsstest weitere LEFT OUTER JOINs anfügen, ganausoviele wie Dein
Kategorienbaum Ebenen ebenen hat.

...
LEFT OUTER JOIN kategorien AS k1
ON k1.id = datensaetze.kategorie

LEFT OUTER JOIN kategorien AS k2
ON k2.id = k1.parent

LEFT OUTER JOIN kategorien AS k3
ON k3.id = k2.parent

usw.

k1.name, k2.name, usw kommen dann in Dein CONCAT_WS().

Das sollte funktionieren. Für eine sauberere, schnellere Lösung solltest
Du Dir überlegen, einen Keyword-Tabelle anzulegen, oder Dir die
MySQL-proprietäre Volltextsuche mit MATCH AGAINST [1] ansehen.
Um Bäume in SQL abzubilden gibt es auch z.T. geschicktere Möglichkeiten
als über eine 'parent'-Spalte [2].

cheers,

-Uli.

[1] http://dev.mysql.com/doc/mysql/en/fulltext-search.html
[2] http://google.com/search?q=b%C3%A4ume+sql

Re: Suche im Kategoriebaum

am 17.07.2005 09:58:29 von skanto

Uli Honal wrote:

> 16.14. Warum soll ich nicht SELECT * schreiben?
> http://www.php-faq.de/q/q-sql-select.html

Tausendmal durchgekaut und hier auch nur für eine bessere Lesbarkeit
verwendet.

> Nur die Tabellennamen solltest Du nochmal überdenken.

Nö, denn das waren ja auch nur Beispielnamen - was drinsteht spielt hier
doch keine Rolle.

> Du müsstest weitere LEFT OUTER JOINs anfügen, ganausoviele wie Dein
> Kategorienbaum Ebenen ebenen hat.

Ja, habe ich so auch getestet, aber leider ist das ziemlich langsam...
Ich habe mir jetzt folgendermaßen geholfen:

Ein zusätzliches Feld in in der Kategoriendatenbank, in dem sämtliche
Namen der übergeordneten Kategorien eingetragen sind. Beim umbenennen
oder "verschieben" der Kategorie oder einer übergeordneten Kategorie
wird gleichzeitig auch der Inhalt des Feldes erneuert.
Klappt gut so :-)

> [1] http://dev.mysql.com/doc/mysql/en/fulltext-search.html
Die Volltextsuche sucht nur nach ganzen Wörtern, oder?

Vielen Dank für die Ratschläge!

Grüße,
Manuel