22 Stimmen

Wie findet man die Ähnlichkeit zwischen mySQL-Zeilen?

Ich versuche, ein Skript zu erstellen, das einen passenden Prozentsatz zwischen meinen Tabellenzeilen findet. Zum Beispiel meine mySQL-Datenbank in der Tabelle Produkte enthält das Feld Name (indiziert, FULLTEXT) mit Werten wie

LG 50PK350 PLASMA TV 50" Plasma TV Full HD 600Hz 
LG TV 50PK350 PLASMA 50"
LG S24AW 24000 BTU
Aircondition LG S24AW 24000 BTU Inverter

Wie Sie sehen können, haben sie alle dasselbe Schlüsselwort. Aber der 1. Name und der 2. Name sind sich ähnlicher. Außerdem haben der 3. und 4. Name mehr ähnliche Schlüsselwörter als der 1. und 2.

Meine mySQL-DB enthält Tausende von Produktnamen. Ich möchte die Namen finden, die mehr als einen bestimmten Prozentsatz (sagen wir 60 %) an Ähnlichkeit aufweisen.

Zum Beispiel werden, wie gesagt, 1. und 2. (und jeder andere Name), die zu mehr als 60 % übereinstimmen, in einem gruppenähnlichen Format angezeigt, damit ich weiß, dass diese Produkte ähnlich sind. 3. und 4. und alle anderen, die zu mehr als 60 % übereinstimmen, werden in einer anderen Gruppe wiedergegeben, um mir mitzuteilen, dass diese Produkte übereinstimmen.

Wenn es möglich ist, wäre es toll, die Schlüsselwörter, die alle gruppierten übereinstimmenden Namen erfüllen, auszugeben. Zum Beispiel LG S24AW 24000 BTU ist das Schlüsselwort, das im 3. und 4. Namen enthalten ist.

Am Ende werde ich eine Liste mit all diesen Stichwörtern erstellen.

Was ich jetzt habe, ist die folgende Abfrage (wie Jitamaro vorgeschlagen)

Select t1.name, t2.name From products t1, products t2

die ein neues Namensfeld neben allen anderen Namen erzeugt. Entschuldigen Sie, dass ich nicht weiß, wie ich es richtig erklären soll, aber das ist, was es tut: (Die echten Werte sind Produktnamen wie oben)

Vor der Abfrage

-name-
A
B
C
D
E

Nach der Abfrage

-name- -name-
A        A
B        A
C        A
D        A
E        A
A        B
B        B
C        B
D        B
E        B
.
.
.

Gibt es eine Möglichkeit, entweder mit mySQL oder PHP, die mir die passenden Namen findet und die Schlüsselwörter extrahiert, wie ich es oben beschrieben habe? Bitte teilen Sie Code-Beispiele.

Vielen Dank an die Gemeinschaft.

6voto

Pedro Lobito Punkte 84666

Abfrage der DB mit LIKE OR REGEXP:

SELECT * FROM product WHERE product_name LIKE '%LG%';
SELECT * FROM product WHERE product_name REGEXP "LG";

Schleifen Sie die Ergebnisse und verwenden Sie similar_text():

$a = "LG 50PK350 PLASMA TV 50\" Plasma TV Full HD 600Hz"; // DB value
$b = "LG TV 50PK350 PLASMA 50\"" ; // USER QUERY

$i = similar_text($a, $b, $p);
echo("Matched: $i  Percentage: $p%");

//outputs: Matched: 21 Percentage: 58.3333333333%

Ihr zweites Beispiel entspricht 62,0689655172 %:

$a = "LG S24AW 24000 BTU"; // DB value
$b = "Aircondition LG S24AW 24000 BTU Inverter" ; // USER QUERY

$i = similar_text($a, $b, $p);
echo("Matched: $i  Percentage: $p%");

Sie können einen höheren Prozentsatz als, sagen wir, 40 % festlegen, um Produkte abzugleichen.
Bitte beachten Sie, dass similar_text() die Groß- und Kleinschreibung berücksichtigt, so dass Sie die Zeichenkette klein schreiben sollten.

4voto

Alix Axel Punkte 146320

Was Ihre zweite Frage betrifft, so ist die levenshtein() Funktion ( in MySQL ) wäre ein guter Kandidat.

2voto

Jeff Ferland Punkte 17180

Wenn ich mir Ihre Beispiele ansehe, überlege ich, wie ich anhand des Titels versuchen würde, ähnliche Produkte zu finden. Bei Ihren beiden Beispielen fällt mir in jeder Zeile vor allem eine Sache auf: die Modellnummern. 50PK350 taucht wahrscheinlich nirgendwo anders auf als in Verbindung mit diesem einen Modell.

MySQL selbst ist nicht darauf ausgelegt, Fragen wie diese zu beantworten, aber einige Zusatztools darüber sind es. Ein Teil des Problems ist, dass die Abfrage all dieser Felder in allen Positionen teuer ist. Sie wollen sie wirklich auf eine bestimmte Weise aufteilen und indizieren. Die Ähnlichkeitsklasse von Lucene vergibt eine hohe Punktzahl für Wörter, die selten in allen Daten vorkommen, aber einen hohen Prozentsatz Ihrer Daten ausmachen. Siehe Erklärung der Similarity Class für Lucene? auf hohem Niveau

Sie sollten sich auch Folgendes ansehen Vergleich von Volltextsuchmaschinen - Lucene, Sphinx, Postgresql, MySQL?

Die Bewertung der einzelnen Wörter anhand der Lucene-Ähnlichkeitsklasse sollte schneller und zuverlässiger sein. Die Summe der Ergebnisse sollte Ihnen die meisten verwandten Produkte liefern. Für den Fernseher würde ich erwarten, dass zuerst exakte Übereinstimmungen angezeigt werden, dann einige andere der gleichen Größe, dann die Marke, dann Fernseher im Allgemeinen, usw.

In jedem Fall sollten Sie sich darüber im Klaren sein, dass Ihre Abfragen zu langsam und zu teuer sein werden, wenn Sie die Datenstrukturen nicht mit einem anderen Tool auf dem SQL-System ändern, um bessere Datenstrukturen zu erstellen. Ich denke, Lucene ist wahrscheinlich der richtige Weg. Sphinx oder andere nicht erwähnte Optionen können ebenfalls in Betracht gezogen werden.

1voto

J0HN Punkte 25228

Eine mögliche Lösung ist die Verwendung von Damerau-Levenstein-Abstand . Sie könnte wie folgt verwendet werden

select *
from products p
where DamerauLevenstein(p.name, '*user input here*')<=*X*

Sie müssen herausfinden, welches X am besten zu Ihren Bedürfnissen passt. Es sollte eine ganze Zahl größer als Null sein. Sie können es fest codieren, parametrisieren oder nach Bedarf berechnen lassen.

Das Schwierigste dabei ist DamerauLevenstein . Es muss eine gespeicherte Prozedur sein, die den Damerau-Levenstein-Algorithmus implementiert. Ich habe kein MySQL hier, also werde ich es vielleicht später am Tag für Sie schreiben.

Aktualisierung: MySQL unterstützt keine Arrays in gespeicherten Prozeduren, daher gibt es keine Möglichkeit, Damerau-Levenstein in MySQL zu implementieren, außer der Verwendung einer temporären Tabelle für jeden Funktionsaufruf. Und das wird zu einer schrecklichen Leistung führen. Sie haben also zwei Möglichkeiten: Schleife durch die Ergebnisse in PHP mit levenstein wie Alix Axel vorschlägt, oder migrieren Sie Ihre Datenbank zu PostgreSQL, wo Arrays unterstützt werden. Es gibt auch die Möglichkeit, eine benutzerdefinierte Funktion zu erstellen, aber das erfordert das Schreiben dieser Funktion in C, das Verknüpfen mit MySQL und möglicherweise den Neuaufbau von MySQL, so dass Sie auf diese Weise nur noch mehr Kopfschmerzen verursachen.

1voto

Halcyon Punkte 55829

Das ist komplizierter als es scheint, und in Ihrem Beitrag fehlen einige Informationen:

  • Wie werden die Leute diese Funktion zur automatischen Vervollständigung nutzen?
  • Ist es wichtig, dass Sie alle Namen für ein Produkt finden können? Denn offensichtlich benennen nicht alle Geschäfte ihre Produkte ähnlich, so dass ein Angestellter das Produkt, das er gefunden hat, möglicherweise nicht finden kann.
  • Haben Sie Informationen darüber, welche Produktnamen für dasselbe Produkt stehen?
  • Ist es relevant, in welchem Geschäft Sie suchen? Wo wird diese automatische Vervollständigung verwendet?
  • Sollte die Autovervollständigung wirklich nur Produkte vorschlagen, die mit todos die Worte, die Sie getippt haben (es ist technisch nicht so schwer, Tippfehler zu korrigieren)

Ich denke, Sie brauchen ein klareres Bild davon, was Sie (oder besser: die Benutzer) mit dieser Funktion zum automatischen Vervollständigen erreichen wollen.

Eine Autovervollständigungsfunktion ist eine sehr benutzerfreundliche Funktion. Sie hilft dem Benutzer, möglicherweise auf unscharfe Weise, so dass es keine einzige richtige Antwort gibt. Man muss herausfinden, was am besten funktioniert, und nicht, was technisch am einfachsten zu machen ist.

Überlegen Sie zuerst, was Sie wollen, und machen Sie sich dann Gedanken über die Technik.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X