2010-12-10 14 views
0

Ich bin auf der Suche nach einer Möglichkeit, mehrere Spalten in einer SQL-Tabelle mit mehreren Schlüsselwörtern mit Coldfusion zu suchen. Ich habe derzeit den folgenden Code, der halb funktioniert.SQL Query - Mehrere Schlüsselwörter suchen Multi Spalten

<cfquery name="rsSearchEmployees" datasource="#request.database#"> 
SELECT idn, firstname, lastname 
FROM Employees 
WHERE (<cfloop list="#arguments.nameSearchString#" delimiters=" " index="word">firstname LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="%#Trim(word)#%" /> OR </cfloop> (1 <> 1)) 
OR (<cfloop list="#arguments.nameSearchString#" delimiters=" " index="word">lastname LIKE <cfqueryparam cfsqltype="cf_sql_varchar" value="%#Trim(word)#%" /> OR </cfloop> (1 <> 1)) 
ORDER BY firstname ASC 

Es sucht 2 Spalten, Vorname und Nachname mit Keywords in ein Textfeld eingegeben. Die Schlüsselwörter werden mit dem Tag cfloop zerlegt.

Dieser Code führt zwar zu Ergebnissen, entfernt jedoch derzeit keine Ergebnisse, wenn 2 oder mehr Schlüsselwörter in einer oder beiden Spalten nicht gefunden werden.

Zum Beispiel, ich wollte nach Steve Smith suchen, wenn ich Steve eintippe, zeigt es die Zeile für Steve. Dasselbe passiert für Smith. Wenn ich Steve Smith eintippe, zeigt es immer noch die Zeile an, die korrekt ist.

Es geht schief, wenn ich etwas wie Steve Jobs eintippe. Wenn er dies eingibt, zeigt er immer noch Steve Smith, wenn er es nicht tun sollte. Hat jemand eine Ahnung, wie man das schafft?

Vielen Dank für jede Hilfe im Voraus. Chris

+0

Gibt es einen Grund, warum Sie Ihr 'OR' in der' WHERE' -Klausel nicht zu einem 'AND' ändern können? – JNK

+0

Welches Ergebnis willst du für "Smith steve"? –

+0

Ich kann die Bedingungen ändern, versuchte alle verschiedenen Variationen, aber alle liefern nicht die richtigen Ergebnisse. Mit Steve Smith will ich, dass es das Ergebnis zeigt, ich will nicht, dass es ein Ergebnis für Steve Jobs zeigt. Danke – Chris

Antwort

2

Chris gesucht wird,

Ich denke, das Herz Ihres Problems ist, dass Ihre Logik sagt derzeit "Zeigen Sie mir alle Datensätze, wo Vorname oder Nachname eines der Wörter in der Suchzeichenfolge übereinstimmt". Sie erlauben jemandem, nach "Matthew Mark Luke John" als Zeichenfolge zu suchen, um Personen mit JEDEM dieser Namen zu erreichen, anstatt das Suchwort nur als einen einzelnen Namen zu behandeln.

Dies verursacht die Tatsache, dass die Aufzeichnung "Steve Jobs" für Suche = "Steve Smith" wegen der Übereinstimmung nur auf firstName kommt. Klingt wie die SQL-Logik zu breit ist.

Hört sich so an, als würde eine Suche die Zeichenfolge stattdessen als vollständigen Namen (Vorname + Nachname) anstelle einer Liste mehrerer Namen behandeln, mit denen sie übereinstimmen soll. Wenn jedoch mehr als ein Wort zur Verfügung gestellt wird, möchten Sie schnell auf Datensätze beschränken, die mit ALLEN Wörtern übereinstimmen, nicht mit ANY.

Namen können komplizierte Dinge sein, wobei Vor- oder Nachname mehrere Wörter sind. Dies wirft einige kleinere Schwierigkeiten auf.

Gewünschtes Ergebnis:

  • Search "Alle" - Aufzeichnungen
  • Search "Alle Smith" mit Vor- oder Nachnamen von 'Allen' bringen Aufzeichnungen bringen mit beiden Vor- und Nachnamen Streichhölzern gegen ‚Allen‘ und/oder ‚Smith‘

Diese Abfrage in Suchbegriff beliebige Anzahl der Wörter können aber nur zeigen Datensätze, die jedes Wort in irgendeiner Art und Weise übereinstimmen (erlaubt Namen in jeder Suche Bestellung, z. Erstes letztes oder letztes erstes). Das ist wahrscheinlich das, was du willst.

SELECT idn, firstname, lastname 
FROM Employees 
WHERE 1=1 
<cfloop list="#arguments.nameSearchString#" delimiters=" " index="word"> 
    AND (firstname like <cfqueryparam cfsqltype="cf_sql_varchar" value="#word#%" /> 
    OR lastname like <cfqueryparam cfsqltype="cf_sql_varchar" value="#word#%" />) 
</cfloop> 
+0

Danke Mujimu, das funktioniert perfekt und habe es jetzt umgesetzt !!! – Chris

+0

Gerne helfen ... – mujimu

+0

Das ist toll, aber zum Vorteil anderer, ich bekam keine Rückkehr auf meine Suche "Ford Falcon", bis ich ein "%" in FRONT Wert = "# Wort #% hinzugefügt ", dh Wert ="% # Wort #% " – user460114

1

Dass Sie beide Seiten Ihrer LIKE-Klauseln mit Prozenten umhüllen, sagt mir, dass Sie wirklich etwas Fuzzy-ish-Matching wollen. Ich würde mit SQL-WHERE-Anweisungen überspringen und stattdessen eine Volltextlösung verwenden. Optionen umfassen:

  1. Datenbank Volltext-Indexierung: SQL Server, Oracle und MySQL haben alle Lösungen.
  2. Suchmaschine: Coldfusion 9 Schiffe sowohl mit Verity und SOLR

Jede dieser Optionen wird Ihr Leben viel einfacher und vermeidet die komplexe UND/ODER WIE Logik Sie WHERE-Klausel in einer SQL einführen müssen machen würden um einen ähnlichen Effekt zu erzielen.

+0

Danke dafür, ich benutze Coldfusion seit geraumer Zeit, aber nur für Anfänger. Ich habe Informationen über Verity gesehen, aber habe keine Ahnung, wie es funktioniert oder wie ich es nutzen kann. Das andere Problem ist die Verwendung von Shared Hosting, also wäre dies betroffen? Diese Abfrage ist Teil einer AJAX-Antwort. – Chris

+1

Shared Hosting kann ein Problem bei der Einrichtung von Verity/SOLR sein, das Sie mit Ihrem Provider besprechen müssen. Wahrscheinlich ist es einfacher, das Volltext-Indexierungs-Setup auf der db-Seite zu bekommen. In beiden Fällen würden Sie eine dieser "Fuzzy-Search" -Lösungen verwenden, um eine Liste von Primärschlüsseln für die employee-Tabelle abzurufen und dann eine SQL-Anweisung auszuführen, um diese mit einer IN-Klausel abzurufen. In beiden Fällen sollte das Senden einer Antwort vom Server im AJAX-Format weiterhin möglich sein. Welche Datenbank benutzt du? – orangepips

+0

Wir verwenden zur Zeit MySQL5 – Chris

0

Machen Sie ein paar Annahmen, so dass Sie immer einen "Vornamen" und "Nachname" eingeben, nach denen suchen und dass Sie auf dem Stub z. Smith ... gibt Smith, Smiths usw. zurück, das könnte es tun. Sie könnten in Ihrer führenden% setzen zurück, wenn Sie wirklich Schmied, Ironsmith wollen passen usw.

<cfquery name="rsSearchEmployees" datasource="#request.database#"> 
SELECT idn, firstname, lastname 
FROM Employees 
WHERE firstname like <cfqueryparam cfsqltype="cf_sql_varchar" value="#Trim(word)#%" /> 
AND lastname like <cfqueryparam cfsqltype="cf_sql_varchar" value="#Trim(word)#%" /> 
</cfquery> 

Sie könnte eine Alternative Run „oder“ SQL, wenn nur ein Wort für