2009-08-14 9 views
1

ich eine Zeile in meiner MySQL-Tabelle passenden Text zu einer Reihe

John - Hey (johnnny) 

wie so

haben aber wegen der, wie der String formatiert wurde habe ich

john hey johnnny 

Ich habe diese Abfrage versucht

$q = mysqli_query($id,"SELECT * FROM mixes WHERE `tracklist` LIKE %".$_REQUEST['did']."%"); 

aber das hat nicht funktioniert? Irgendwelche Ideen?

+0

Nicht sicher, dass ich folge. Bitte klären Sie? Wo formatierst du die Zeichenfolge (wie oben in der dritten Zeile deines Posts erwähnt) und woher bekommst du die Eingabe? –

+1

Sie versuchen also, eine Spalte abzufragen, die Fremdzeichen enthalten kann oder nicht, und möchten die Tabelle ohne diese überflüssigen (d. H. Nicht alphabetischen) Zeichen durchsuchen? –

+0

Die Zeichenfolge kommt aus einer anderen MySQL Tabelle, aber es wird gestreift von seinem - und(), ich muss die Zeile mit John - Hey (johnnny) ziehen, aber ohne die - und die() wenn das möglich ist –

Antwort

2

Folgen Sie der Frage nicht vollständig und ich bin ein Postgres-Typ, aber meine beste Vermutung ist, dass Sie den Parameter in Anführungszeichen einschließen müssen.

$q = mysqli_query($id,"SELECT * FROM mixes WHERE `tracklist` LIKE '%{$_REQUEST['did']}%'"); 
+0

Eigentlich bin ich hübsch sicher, dass was er schrieb, ist gültig php. Das '.' fügt nur Strings zusammen, wenn also [did] 'test' enthielt, würde seine Abfrage aussehen wie "... wo' tracklist' LIKE% test% ". –

+0

Da der Parameter Leerzeichen enthalten kann, ist das Einkapseln in Anführungszeichen der richtige Ansatz, wie oben gezeigt. – AvatarKava

+0

Ah. Nie zuvor geschweifte Klammern in PHP verwendet. Danke für die Information. –

1

Sie vielleicht einen Blick auf die full text indexes/search in MySQL haben wollen. Ich denke, der natürliche Sprachenmodus sollte in der Lage sein, Ergebnisse für den Suchstring unabhängig von der Wortstellung, Interpunktion usw. zu finden.

Beachten Sie, dass dies nur mit MyISAM-Tabellen funktioniert.

+0

versuchen, eine Abfrage wie folgt: $ q = mysqli_query ($ ID, "SELECT * FROM Mixe WHERE MATCH (Trackliste) GWAINST ('". $ _ REQUEST [' Did ']. "')"); kein Erfolg die Tabellen Myisam auch –

+0

Ist mixs.tracklist Teil eines FULLTEXT-Index? – outis

+0

"SELECT * FROM Mixe WHERE MATCH (Titelliste) GEGEN ('john hey johnnny');" funktioniert in meinen Tests darin, dass es eine Zeile mit "John - Hey (johnnny)" gefunden hat, aber es hatte auch einige falsche Positive (zB stimmte es mit "Die Ballade von John und Yoko, Johnny B. Goode, Hey Jude" überein). – outis

1

Sie müssen den gleichen Parameter in eine ' umbrechen. Sie haben die folgende:

$q = mysqli_query($id,"SELECT * FROM mixes WHERE `tracklist` LIKE %".$_REQUEST['did']."%"); 

Es sollte:

$q = mysqli_query($id,"SELECT * FROM mixes WHERE `tracklist` LIKE '% ".$_REQUEST['did']."%'"); 

Beachten Sie die zwei Apostrophe ich vor dem ersten und letzten % ‚s

bearbeiten

setzen Also, wenn Sie die Eingabe john hey johnnny' and your looking for John - Hey (Johnnny) `in der Datenbank bekommen, dann müssen Sie manipulieren die Zeichenfolge Sie suchen für

$search = str_replace(" ", "%", $_REQUEST['did']); // john%hey%johnnny 

$query = "SELECT * FROM mixes WHERE `tracklist` LIKE '".$search."'"; 
$q = mysqli_query($id, $query); 

Die % werden Sie zwischen denen alle Leerzeichen oder Zeichen übereinstimmen müssen. Dies wird nicht mit der Endung ) übereinstimmen. Aber es wird die Reihe auswählen, wenn das gut genug ist. Sie können die % vor und nach der $search Variable hinzufügen, um die Endung ) und oder alle Zeichen vor der Zeichenfolge, die Sie suchen.

+0

Absolut, aber seine Anfrage wird immer noch nicht funktionieren, weil 'John hey Johnny'! = 'John - Hey (johnnny)', was er eigentlich sucht. Die einzigen Lösungen, die ich gefunden habe, sind ziemlich hässlich (mit sps oder Funktionen, um nicht-alphanumerische Zeichen aus der Zeichenkette auszublenden). Vielleicht hat jemand hier eine bessere Lösung. –

0

Einige Optionen sind:

  1. Schreiben Sie eine Funktion, die nicht-alphanumerische Zeichen und Leerzeichen Streifen und es Spalte tracklist in der Suchabfrage. Ein großer Nachteil ist, dass Ihre Abfrage keine Indizes unter tracklist verwenden kann.
  2. Verwenden Sie eine Form von Fuzzy-Matching. Dies wird höchstwahrscheinlich auch keine Vorteile aus Indizes ziehen. Es gibt Tom Haighs Vorschlag, der die Zeile in Ihrem Beispiel finden wird, aber auch falsche Positive zurückgeben kann.Sie könnten auch REGEXP/RLIKE verwenden, die Fuzzy Matching nicht ausführen, aber Sie können einen Ausdruck erstellen, die funktioniert:

    $tracklist=preg_replace('/[^a-z]+/i', '[^[=a=]]+', $_REQUEST['did']); 
    $q = mysqli_query($id,"SELECT * FROM `mixes` WHERE `tracklist` REGEXP '$tracklist'"); 
    

    das Beispiel verwenden $_REQUEST['did'] von ‚johnny hey Johnnny‘, die resultierende Abfrage * FROM Mixes „SELECT wird WO tracklist REGEXP 'John [^ [= a =]] + hey [^ [= a =]] + Johnnny' ". Das obige ignoriert nicht alphabetische Zeichen. Wenn Sie möchten, nicht-alphanumerische Zeichen ignorieren, versuchen Sie eine der folgenden (die zweite nicht ignorieren ‚_‘):

    $tracklist=preg_replace('/[^a-z0-9]+/i', '[^[:alnum:]]+', $_REQUEST['did']); 
    
    $tracklist=preg_replace('/\W+/', '[^[:alnum:]_]+', $_REQUEST['did']); 
    
  3. Umstrukturieren die Tabellen und Verarbeitungslogik. Dies ist die meiste Arbeit, wird aber die konzeptionell sauberste Implementierung hervorbringen. Ich nehme an, dass tracklist eine $ delim (zB Komma, Semikolon, ...) getrennte Liste von Titelnamen ist. Wenn ja, mixes ist nicht einmal . Erstellen Sie eine neue tracklist Tabelle:

    CREATE TABLE `tracklist` (
        mix INTEGER REFERENCES mixes (id), 
        position INTEGER NOT NULL, 
        track INTEGER REFERENCES tracks (id), 
        PRIMARY KEY (mix, position), 
        KEY (mix, track), 
        KEY (track) 
    ) ENGINE=InnoDB; 
    

    Um die Mischung für eine bestimmte Spur zu finden, führen Sie einen Join:

    SELECT mixes.* FROM mixes 
        JOIN tracklist 
         ON mixes.id = tracklist.mix 
        WHERE tracklist.track=$trackid 
    

    Durch die Verwendung von Indizes, die obige Abfrage wird schneller sein als die beiden anderen Optionen . Der Hauptnachteil dieses Ansatzes besteht darin, dass Sie mehr Abfragen durchführen müssen, um die Trackliste für einen Mix zu erhalten. Ein Vorteil ist, dass die Bearbeitung der Trackliste verbessert werden kann. Bei entsprechend definierten Indizes kann diese Option immer noch schneller sein als Ihr aktuelles DB-Design. Zum Beispiel

    SELECT t2.mix, t2.position, tracks.* 
        FROM tracklist AS t1 
        JOIN tracklist AS t2 
         ON t1.mix = t2.mix 
        JOIN tracks 
         ON t2.track = tracks.id 
        WHERE t1.track=:trackid 
    

    wird sehr effizient sein, wenn es Indizes auf tracklist.tracks, tracklist.mix und tracks.id, die eine sehr vernünftige Annahme ist, angesichts der obigen Definition von tracklist und dass track.id ist höchstwahrscheinlich eine Primärschlüsselspalte. MySQL muss nur (number of mixes containing track :trackid) + (total number of tracks in all mixes that contain :trackid) * 2 rows untersuchen. Wenn es zwei Mischungen gibt, die "Johnny, Hey (johnnny)" mit 8 bzw. 10 Spuren enthalten, untersucht MySQL 38 Zeilen insgesamt (20 von tracklist und 18 von tracks). Die Optionen 1 und 2 müssen (number of mixes) Zeilen untersuchen. Solange die Anzahl der Mixe viel größer als die durchschnittliche Mix-Größe ist und die gesuchte Spur in vielen Mischungen nicht angezeigt wird, ist diese Option schneller als die anderen beiden.

Beachten Sie, dass, wenn Sie $_REQUEST['did'] sanieren, bevor die Abfrage konstruieren, Ihr Skript SQL injection offen ist ([2], [3]). Das obige Beispiel in Option 2, das REGEXP verwendet, ist sicher (Desinfektion ist ein Nebeneffekt der preg_replace), aber der sicherste, allgemeinste Ansatz ist die Verwendung prepared queries.

$q = mysqli_prepare($id,"SELECT * FROM `mixes` WHERE `tracklist` REGEXP ?"); 
    $q->bind_param('s', $_REQUEST['did']); 
    $q->execute(); 

Sie können auch vorbereitete Abfragen wieder verwenden, die die DB bedeutet nicht die Abfrage Analysepunkte müssen, damit Geschwindigkeit verbessert wird.

function findMixFor($track) { 
     global $id; 
     static $q = Null; 
     if (is_null($q)) { 
      $q = mysqli_prepare($id,"SELECT * FROM `mixes` WHERE `tracklist` REGEXP ?"); 
     } 
     $q->bind_param('s', $track); 
     $q->execute(); 
     return $q; 
    } 

Beachten Sie, dass findMixFor ist nur eine vorbereitete Abfrage zu veranschaulichen Wiederverwendung. Eine ordnungsgemäße Implementierung würde den gesamten DB-Zugriff in einer Datenzugriffsebene isolieren und auch Fehler behandeln.

Sie könnten auch in Verwendung von PDO statt mysqli suchen. Zum einen ist die Unterstützung für vorbereitete Abfragen viel reicher. Zum anderen erleichtert es den Wechsel zwischen Datenbanken.

+0

Kannst du mir sagen, dass mir heute langweilig ist? – outis

0

Es gibt eine breitere Frage - warum versuchen Sie, dies zu erreichen und was ist das Problem, das Sie versuchen zu lösen?

Ich denke, dass Ihr Problem viel tiefer ist - Sie lösen nicht das richtige Problem. Was versuchst du wirklich?

Verwandte Themen