SQL Select aus mehreren Feldern mit einem Eingabefeld

  • Ersteller Ersteller Cave Johnson
  • Erstellt am Erstellt am
C

Cave Johnson

Gast
Hi,

ich habe eine MySQL-DB mit den Feldern name, strasse, plz, ort.

Am liebsten hätte ich jetzt - wie bspw. Google Maps - ein einziges Eingabefeld um eine Adresse zu suchen. D.h. ich kann einfach Firma XY München eingeben und bekomme die entsprechenden Ergebnisse.

Folgendes liefert mir alles in München, nicht nur Firma XY:
PHP:
".. WHERE strasse IN ('firma','xy','münchen') OR name IN ('firma','xy','münchen') OR ..";
Folgendes liefert gar nichts, weil ja in diesem Beispiel keine Straße gefunden wird:
PHP:
".. WHERE strasse IN ('firma','xy','münchen') AND name IN ('firma','xy','münchen') AND ..";

Wie macht man das am intelligentesten?
 
ganz allgemein, indem du den ergebnissen eine wahrscheinlichkeit zuordnest.

ein beispiel: jeder begriff "firma" "XY" "münchen" wird abgefragt, der eintrag mit den meisten ergebnissen ist vermutlich der gesuchte. falls zwei zutreffen, müssten eben auch zwei angezeigt werden. wenn du nur münchen eingibst, kommen alle firmen.

"nachteil": du hast bei x begriffen auch x db abfragen plus den vergleich der ergebnis -> mehr aufwand ... für google kein problem, für dich vllt. schon

alternativ kannst du auch so vorgehen: erst alles zusammenabfragen, wenn ein ergebnis gefunden wurde -> anzeigen
wenn nicht, jeweils ein teil auslassen und nochmal abfragen.
also erstes mal "firma" "XY" "münchen"
zweites mal "firma" "XY", "firma" "münchen", "XY" "münchen"
usw...

das reduziert die anzahl der abfragen, insbesondere, wenn du aufpasst und überschneidungen/mehrmals das selbe abfragen, vermeidest
 
Zuletzt bearbeitet:
Das mach ich dann nach dem Query direkt vor der Ausgabe, oder geht das im Select?
Bzw. müsste ich das ja vor der Ausgae noch zwischenspeichern und nach "Treffer-Anzahl" sortieren.

Ich kann auch ein LIMIT einbauen, das wäre kein Problem falls bspw. jemand nur den Ort eingibt.
 
Wie wäre es mit einer (temporären) Tabelle?
Also
Code:
insert into temp(wert,key)select name,ID from tab;
insert into temp(wert,key)select ort,ID from tab;
insert into temp(wert,key)select strasse,ID from tab;
...
und dann
Code:
@erg=select count(key),key from temp where wert IN ('firma','xy','münchen') order by count(key) desc limit 10;
select * from tab where ID IN @erg.row(1)
was dann das selbe sein sollte wie
Code:
select * from tab right join (select count(key),key from temp where wert IN ('firma','xy','münchen') order by count(key) desc limit 10) on key=ID
(Hoff mal, dass das geht...)
 
http://dev.mysql.com/doc/refman/5.1/de/fulltext-search.html

Mit ein paar kreativ gesetzten Indizes könnte die Volltext-Suche durchaus zu netten Ergebnissen führen, da sie eine Gewichtung mitbringt.

Alternativ: Use the source, Luke!
Einige der großen CMS bieten richtig gute Suchmaschinen. Contao hat z.B. eine verdammt mächtige indexbasierte Volltext-Suche. Warum selbst erfinden, wenn es bereits Lösungen unter GPL gibt? Lesen, verstehen, adaptieren... ist meist schneller und billiger als das Rad neu zu erfinden. Mit etwas Glück kann man sogar ne komplette Such-Klasse quasi 1:1 übernehmen.
 
Bin jetzt doch auf die Volltextsuche umgestiegen, da meine u.g. Variante extrem langsam ist. Danke für den Tipp.

Danke für die Ideen, eine temporäre Tabelle halte ich allerdingsfür etwas "unelegant", da ich diese jedesmal füllen und am Ende wieder leeren muss.


Ich habe mir jetzt Folgendes überlegt:

Ich lese alle potentiellen Zeilen aus, in denen eine Übereinstimmung gefunden wurde (obige OR IN (...)-Variante). Vor der Ausgabe prüfe ich dann mit strpos, ob alle eingegebenen Worte in der Zeile enthalten sind, und gebe nur dann etwas aus.

PHP:
$input = "('firma', 'xy', 'münchen')";
$strpos = array("firma", "xy", "münchen");
$flag = true;

// liefert alle Zeilen mit einer Übereinstimmung
$sql = "SELECT CONCAT (name,str,plz,ort) AS string, name, strasse, plz, ort FROM haendler WHERE name IN $input OR strasse IN $input OR plz IN $input OR ort IN $input";
$sql = mysql_query($sql);
while($row = mysql_fetch_object($sql))
{
  // prüfen ob jedes eingegebene Wort in der Zeile enthalten ist
  foreach($strpos as $str) {
    if(strpos(strtolower($string), strtolower($str)) === false) {
      $flag = false;
      break;
    }
  }

  // Ausgabe nur wenn Eingabe vollständig in Zeile enthalten ist
  if($flag !== false) {
    echo $row->name . ", " . $row->str . ", " . $row->plz . " " . $row->ort . "<br />";
  }
  $flag = true;
}
 
Zuletzt bearbeitet:
Zurück
Oben