MySQL suchen in DB nach Person

slimox

Mitglied
Hallo,

Ich habe eine Tabelle mit Feldern wie 'vorname', 'name', 'mail', etc.. Die Tabelle ist in Innodb.

Was ich machen möchte, es gibt ein <input> in welches z.B 'Hans Muster' geschrieben wird.
Nun soll mir php in der DB den Hans Muster ausgeben.. :D

Ich habe es so gelöst:
PHP:
public function search(){
            //Den POST wert exploden
            $search = explode(' ', trim($this->input->post('str')));  
            
            //Nach jedem Array eintrag suchen
            foreach($search as $key => $value){
                $sql = "SELECT * FROM personen WHERE
                            vorname like '".$value."%' 
                            OR 
                            name like '".$value."%' 
                            OR 
                            plz like '".$value."%' 
                            OR 
                            ort like '".$value."%'";
                 $query = $this->db->query($sql);
                 if ($query->num_rows() > 0){
                     foreach ($query->result() as $row){
                         //Person in Array schreiben ... ...
                     $teilnehmer[$row->person_id] = array( 
                           'pid' => $row->person_id,
                           'vorname' => $row->vorname,
                           'name' => $row->name,
                           'plz' => $row->plz,
                           'ort' => $row->ort
                            );

                        }
                     }
                 }
           }
}
So findet es aber nicht nur den Hans Muster, sondern auch alle die im Vorname oder Name, Muster oder Hans haben... :eek: Mit einer Volltext suche kann ich wegen der innodeb nicht...

Wie finde ich nur den Hans Muster:confused: :p
 
Zuletzt bearbeitet:
Dass es das ohne WHERE überhaupt tut... Probier's mal so:

SQL:
SELECT
  *
FROM
  personen
WHERE
  vorname = 'Hans'
  AND name = 'Muster'
 
Wobei ich es etwas unglücklich finde nur ein Textfeld für 2 verschiedene Werte zu verwenden. Was ist wenn jemand nicht "Hans Muster" sondern "Muster Hans" eingibt!?

Nimm doch 2 separate Felder, eines für den Vornamen und eines für den Nachnamen.

NACHTRAG: Nachdem was du jetzt noch geschrieben hast würde ich erst recht empfehlen für jedes Feld das bei der Suche berücksichtigt wird eine eigenes zu nehmen.
 
Dann ist doch aber die Logik des Codes von dir oben korrekt. Du weißt nicht ob nach Namen oder E-Mail gesucht wird (taucht jetzt hier nicht auf, möchte nur das Beispiel fortsetzen), also suchst du in allen Feldern. Dass dann natürlich auch ähnliche Werte dabei rum kommen, ist sicher so gewollt (und bei einer Suche auch sinnvoll).

Du könntest die einzelnen Ergebnisse gewichten (z.B. wenn ein Eintrag exakt ist gibt's mehr Punkte), danach sortieren und dann sortiert ausgeben.
 
Nimm doch 2 separate Felder, eines für den Vornamen und eines für den Nachnamen.
Die Idee ist, es mit einem einzigen zu machen. Es ist logisch, dass es mit 2, 3 etc Feldern viel einfacher ist.

Dann ist doch aber die Logik des Codes von dir oben korrekt. Du weißt nicht ob nach Namen oder E-Mail gesucht wird (taucht jetzt hier nicht auf, möchte nur das Beispiel fortsetzen), also suchst du in allen Feldern. Dass dann natürlich auch ähnliche Werte dabei rum kommen, ist sicher so gewollt (und bei einer Suche auch sinnvoll).
Ja, das stimmt sicher. Wenn jemand nur "Hans" eingibt, dann sollen alle Hänsels kommen. Gibt er noch "Muster" ein also "Hans Muster" und es findet in der DB einen Hans Muster, so soll nur dieser Datesatz ausgegeben werden. Findet es keinen, so kommen alle Musters und Hänsels :D
 
Wenn du es so haben willst, hast du allerdings das Problem, dass du nicht weißt, nach was der Nutzer jetzt suchen will. Ich würde es dann so wie tombe beschrieben hat machen oder ein Feld, das man mittels einer ComboBox umschalten kann (man sagt dem Script also über die ComboBox, nach was man sucht).
 
Die Combobox ist eine Lösung, währe aber super, wenn es ohne geht.

Wenn ich alle Personen wie im Code zuobers in einem Array habe, könnte ich folgendes machen (wie Tim Bureck schrieb)

PHP:
            $anzTreffer = array();
            //Schleife mit allen gefundenen Personen
            foreach($personen as $key => $value){
                //Schleife mit allen Keyworts
                foreach($search as $value2){
                    if(in_array($value2, $value)){
                        //Eins dazuzählen wenn es bei dieser Person vorkommt
                        $anzTreffer[$key] += 1;
                    }
                }
            }
            //Den Array nach Treffer sortieren
            arsort($anzTreffer);
            
            $neu_Personen = array();
            
            $Anzahl_Keyworter = count($search);
            
            //Den Array Personnen Sortieren
            foreach($anzTreffer as $key => $value){
                if($value == $Anzahl_Keyworter){
                    $neu_Personen[] = $personen[$key];
                }
            }

Hat eine Person die Anzahl Treffer = Anzahl Keywort, so kommt alles gesucht bei ihr vor.

Wenn ich die ausgabe über mehrere Seiten verteilen will "Paging" wie kann ich das machen? Bei SQL gibt es den Befehl "LIMIT .. , .." Ist der Ansatz ein ranking mit php zu machen falsch?
 
Zuletzt bearbeitet:
Ich habe mal ein Paging mit php gemacht:
PHP:
            $anzTreffer = array();
            //Schleife mit allen gefundenen Personen
            foreach($personen as $key => $value){
                //Schleife mit allen Keyworts
                foreach($search as $value2){
                    if(in_array($value2, $value)){
                        //Eins dazuzählen wenn es bei dieser Person vorkommt
                        $anzTreffer[$key] += 1;
                    }
                }
            }
            //Den Array nach Treffer sortieren
            arsort($anzTreffer);

            $neu_Personen = array();

            $Anzahl_Keyworter = count($search);

            //Den Array Personnen Sortieren
            foreach($anzTreffer as $key => $value){
                if($value == $Anzahl_Keyworter){
                    $neu_Personen[] = $personen[$key];
                }
            }
            //Überprüfen ob es noch mind eine Person hat
            if(count($neu_Personen) <  1){
                $neu_Personen = array(); //neu setzen
                //Wenn nicht, soll es alle Personnen nehmen die mind. einen treffer haben
                foreach($anzTreffer as $key => $value){
                    $neu_Personen[] = $personen[$key];
                }
            }

            //Total Anzahl Personen nach dem Filtern
            $anz_Personen = count($neu_Personen);

            //Anzahl ergebnisse pro Seite
            $pro_seite = 50;

            //Total Anzahl Seiten
            if($anz_Personen <= $pro_seite){
                $anz_Seiten = 1;
            }else{
                $anz_Seiten = ceil($anz_Personen / $pro_seite);
            }

            //Gewählte Seite
            $select_Seite = $this->input->post('page_nr');

            //Personnen Nr. herausfinden
            if($select_Seite != false){
                $person_nr = ($select_Seite - 1) * $pro_seite;
            }else{
                $person_nr = 1;
            }

            //Gewählte Seite ausgeben
            $ausgabe = array();
            for($i = $person_nr; $i < ($anz_Personen - 1); $i++){
                if(array_key_exists(($i - 1), $neu_Personen)){
                        $ausgabe[] = $neu_Personen[($i - 1)];
                }
            }

            return json_encode($ausgabe);

Jedoch ruft es jetzt jedes mal alle Personen aus der DB, macht ein Ranking... :(

Das Inputfeld sendet ab 3 Zeichen bei jedem weiteren Zeichen eine Anfrage an den Server (Ajax). Bei ein par 100 kann das ja gehen, wie sieht es aus bei ein par 1000**** ;-]
Gibt es nicht eine bessere einfachere Lösung****?
 
Zuletzt bearbeitet:
Ich hoffe mal es schaut sich einer an der Ahnung davon hat:

SQL:
SELECT vorname, nachname, email,  IF(vorname LIKE '%hans%', 1, 0) AS vn, IF(nachname LIKE '%muster%', 1, 0) AS nn FROM personen WHERE vorname like '%hans%' OR nachname LIKE '%muster%' ORDER BY (vn + nn) DESC

Könnte man es nicht so lösen?

Oder besser noch so:

SQL:
SELECT vorname, nachname, email, IF(vorname REGEXP 'hans|muster', 1, 0) AS vn, IF(nachname REGEXP 'hans|muster', 1, 0) AS nn FROM personen WHERE vorname REGEXP 'hans|muster' OR nachname REGEXP 'hans|muster' ORDER BY (vn + nn) DESC
 
Zuletzt bearbeitet:
Zurück