Ich habe eine Datenbank mit Immobilienverzeichnissen und muss eine Liste von Nachbarschaften zurückgeben. Im Moment verwende ich mysql DISTINCT, die alle verschiedenen Werte zurückgibt. Mein Problem ist, dass es viele Nachbarschaften gibt, die ähnliche Namen haben: Beispiel:
%Vor%Ich suche nach einer einfachen PHP- oder MySQL-Lösung, die erkennt, dass "Park View" und "Great Lake" bereits existiert und NUR "Park View" und "Great Lake" zurückgibt.
Mein erster Gedanke ist, wie man die Sortierreihenfolge nach Länge sortiert, so dass die kurzen Werte oben sind und dann mit strstr durchlaufen werden. Das klingt wie eine große Aufgabe Ich frage mich, ob es eine Funktion in mysql oder PHP gibt, die dies leicht tun würde.
Hier sind einige Dinge, die Sie ausprobieren können; Vermutlich suchst du sowohl nach genauen Übereinstimmungen als auch nach nahen Übereinstimmungen.
Suchen Sie zuerst nach einer genauen Übereinstimmung. Suchen Sie dann nach einer LIKE-Übereinstimmung mit dem Namen REVERSED. Dann suchen Sie nach dem Spiel mit den wenigsten zusätzlichen Zeichen.
Hier ist eine Abfrage, die all das tun wird. Beachten Sie, dass Sie den umgekehrten Ortsnamen in einer indizierten Spalte speichern müssen, wenn dies effizient sein soll.
%Vor% Beachten Sie, wie diese UNION-Abfrage ordinal
verwendet, um die beste Übereinstimmung herauszufinden.
Schau es dir hier an: Ссылка
Sie können PHPs similar_text
verwenden, um eine einfache Lösung zu implementieren. Wenn Sie Ihre Daten so vorsortieren, dass die kürzeren, gewünschten Adressen zuerst angezeigt werden, sollte es gut funktionieren. Auch wenn "verschiedene" Adressen nicht zu ähnlich sind, wird es besser funktionieren (aber Sie können immer den Schwellenwert erhöhen):
Für andere Alternativen können Sie auch in PHPs levenshtein
und soundex
, sowie MySQLs SOUNDEX()
.
Eine andere Pseudo-Fuzzy-Methode besteht darin, die Adressen alphabetisch (entweder über MySQL oder PHP) zu sortieren und nacheinander durchzuschleifen; Wenn die aktuelle Adresse beginnt und der Text einer eindeutigen Adresse bereits gefunden wurde, löschen Sie sie. Dies funktioniert ziemlich ähnlich wie bei der Verwendung einer tatsächlichen Fuzzy-Methode, aber es ist direkter auf den Punkt:
%Vor% Diese Methode funktioniert nur, wenn sie sortiert sind, da die kürzere Adresse Park View
vor Park View Sub 1
gefunden werden müsste. Wenn Ihre Adressen zu ähnlich sind und die obige Methode similar_text
einen zu viel ablöst, können Sie diese letztere Funktion versuchen, da sie strenger ist.
Die unten stehende Beispielabfrage wird Ihnen die angegebene Ergebnismenge mit MySQL liefern, aber es ist nicht wirklich "unscharf", zumindest würde ich den Algorithmus nicht beschreiben. (Dies implementiert den von Ihnen beschriebenen Algorithmus - sortiert nach Werten und überprüft dann jeden Wert, um festzustellen, ob der führende Teil mit einem zuvor abgerufenen Wert übereinstimmt.)
Dies findet eine "exakte Übereinstimmung" des führenden Teils des Nachbarschaftswertes mit dem Wert von vorher abgerufenen Zeilen, es gibt nicht wirklich "Unschärfe" bezüglich der Übereinstimmung.
Wenn die Abfrage auf einen Wert trifft, der "nicht übereinstimmend" ist, wird der Wert als "nicht übereinstimmend" markiert. Für den nächsten abgerufenen Wert überprüft er, ob dieser Wert mit dem zuvor "nicht übereinstimmenden" Wert beginnt; Wenn der führende Teil der Zeichenfolge genau übereinstimmt, wird der Wert verworfen. Andernfalls wird der Wert als "nicht übereinstimmender" Wert markiert und beibehalten.
Dieser Ansatz verwendet Inline-Views (oder "abgeleitete Tabellen", wie MySQL sie bezeichnet). Die innerste Inline-Ansicht (aliased als s) erhält eine sortierte Liste verschiedener Werte für die Nachbarschaft. Der "Trick" (wenn Sie es so nennen wollen) befindet sich in der nächsten Inline-Ansicht (alias "t"), wo wir MySQL-Benutzervariablen verwenden, um auf einen zuvor abgerufenen Wert zu verweisen.
Um Probleme mit "Sonderzeichen" zu vermeiden, führen wir einen Gleichheitsvergleich mit den führenden Zeichen durch.
Hier ist die ganze Frage:
%Vor%Es ist alles ziemlich einfach, abgesehen von der Initialisierung der Variable @match und dem Ausdruck, der den Vergleich des aktuellen Werts mit einem vorherigen Wert durchführt.
Wenn wir uns nicht mit den Eckfällen beschäftigen, die durch Sonderzeichen in den Werten eingeführt werden, können wir einen einfacheren LIKE oder REGEXP verwenden, um den Vergleich durchzuführen:
%Vor%Der LIKE-Operator unterliegt den Unterstrichen und Prozentzeichen, der REGEXP unterliegt Sonderzeichen, die in regulären Ausdrücken verwendet werden. Um dieses Problem zu vermeiden, verwendet die obige Abfrage einen Vergleich, der etwas unhandlicher aussieht:
%Vor%Was das tut, ist, den vorherigen Wert (zB @match: = 'Park View') zu nehmen und diesen mit dem führenden Teil (bis zur Länge von 'Park View') des nächsten Wertes zu vergleichen, um festzustellen, ob es ein a ist Übereinstimmung.
Ein Vorteil des Ansatzes mit dieser Abfrage besteht darin, dass die zurückgegebenen Werte garantiert sind, um in einem Prädikat in einer nachfolgenden Abfrage "übereinzustimmen". Angenommen, Sie verwenden diese Abfrage, um eine Liste von Nachbarschaften zu erhalten, und der Benutzer hat eine ausgewählt. Dies wird eine Reihe von Werten zurückgeben, die zu jeder einzelnen Zeile "passen".
Eine nachfolgende Abfrage kann einen der zurückgegebenen Werte in einem einfachen Prädikat (WHERE-Klausel) verwenden, um übereinstimmende Zeilen zurückzugeben. Zum Beispiel, wenn der Benutzer den Wert 'Great Lake' ausgewählt hat:
%Vor%Wenn wir ein LIKE- oder REGEXP-Prädikat für die Übereinstimmung verwendet haben, möchten wir die entsprechende Übereinstimmung im Prädikat der folgenden Abfrage verwenden:
%Vor%