2013-04-16 19 views
10

Mam ciąg znaków zawierający słowa kluczowe rozdzielone przecinkami. Na przykładMySQL i PHP: wiele słów kluczowych

$keywords = 'keyword1, keyword2, keyword3'; 

My schemat Tabela nazwie tbl_address jest tak (uproszczonych)

id  INT(11)  PRIMARY KEY, AUTO INCREMENT 
address VARCHAR(250) NOT NULL 

Załóżmy, trzeba użyć MySQLi w PHP (nie PDO).

Oto moje obecne podejście:

$result = array(); 
$keyword_tokens = explode(',', $keywords); 
foreach($keyword_tokens as $keyword) { 
    $keyword = mysqli_real_escape_string(trim($keyword)); 
    $sql = "SELECT * FROM tbl_address WHERE address LIKE'%$keyword%'"; 
    // query and collect the result to $result 
    // before inserting to $result, check if the id exists in $result. 
    // if yes, skip. 
} 
return $result; 

Podejście to działa, ale nieskuteczny w wydajności. Jeśli jest dużo słów kluczowych, będzie dużo zapytań.

Moje pytanie brzmi, czy istnieje lepszy sposób na osiągnięcie tego samego celu? tj. jaki jest najprostszy sposób na zwrócenie wszystkich rekordów z adresem zawierającym KAŻDY ze słów kluczowych?

+0

To może pomóc: http: // stackoverflow.com/a/9736386/1983854 – fedorqui

+0

Łączenie "LIKE" i "IN": http://stackoverflow.com/questions/1865353/combining-like-and-in-for-sql-server – Chris

+2

@Shivian Serio, dlaczego nie " czy używasz mojego jednego liniowca REGEXP? – Jimbo

Odpowiedz

17

Prosty REGEXP może być tym, na co masz ochotę. Musiałbyś sprawdzić, jak efektywny jest dla ciebie.

SELECT * FROM tbl_address WHERE field REGEXP 'keyword1|keyword2|keyword3';

+1

+1, to było dokładnie to, czego szukałem, nauczyłem się także nowej funkcji 'MySQL' string! –

+1

Doskonała odpowiedź, to pomogło mi rozwiązać tygodniową wartość badań i pomogło mi przeskoczyć ponad 30% mojego problemu :) – Birdy

5
SELECT * FROM user; 
+---------+----------+ 
| user_id | username | 
+---------+----------+ 
|  101 | Adam  | 
|  102 | Ben  | 
|  103 | Charlie | 
|  104 | Dave  | 
+---------+----------+ 

SELECT * 
    FROM user 
    WHERE FIND_IN_SET(username,'adam,ben,dave') > 0; 
+---------+----------+ 
| user_id | username | 
+---------+----------+ 
|  101 | Adam  | 
|  102 | Ben  | 
|  104 | Dave  | 
+---------+----------+ 
+0

Po prostu parę zastrzeżeń z tym podejściem. Nie można użyć składni LIKE i nie przycina słów kluczowych ... – arraintxo

0

najlepszym sposobem jest po prostu stworzyć łańcuch wyszukiwania klauzuli WHERE i dołączyć go do zapytania i uruchom go raz.

$result = array(); 
$keyword_tokens = explode(',', $keywords); 
$where = '';$i=0 
foreach($keyword_tokens as $keyword) { 
    $where.= " address LIKE'%".mysqli_real_escape_string(trim($keyword))."%' OR "; 
} 
    // trim last OR with substr_replace 
    substr_replace($where, "OR", -1, 1); 
    $sql = "SELECT * FROM tbl_address WHERE $where"; 

return $result; 
0

Hi utworzyć kwerendę z unii i wykonać w końcu pętli

$result = array(); 
$keyword_tokens = explode(',', $keywords); 
$sql = ''; 
foreach($keyword_tokens as $keyword) { 
    $keyword = mysqli_real_escape_string(trim($keyword)); 
    if (!empty($sql)) $sql .= " UNION "; 
    $sql .= "SELECT * FROM tbl_address WHERE address LIKE'%$keyword%'"; 
    // query and collect the result to $result 
    // before inserting to $result, check if the id exists in $result. 
    // if yes, skip. 
} 

wykonać zapytanie tutaj.

3

Wystarczy tylko się 'lub', nic innego ...

<?php 

$result = array(); 
$keyword_tokens = explode(',', $keywords); 
$keyword_tokens = array_map('mysqli_real_escape_string', $keyword_tokens); 

$sql = "SELECT * FROM tbl_address WHERE address LIKE'%"; 
$sql .= implode("%' or address LIKE '%", $keyword_tokens) . "'"; 

// query and collect the result to $result 
// before inserting to $result, check if the id exists in $result. 
// if yes, skip. 

return $result; 

edit: Żeby mieć pewność, że również przycinać słowa kluczowe

<?php 

$result = array(); 
$keyword_tokens = explode(',', $keywords); 
$keyword_tokens = array_map(
    function($keyword) { 
     return mysqli_real_escape_string(trim($keyword)); 
    }, 
    $keyword_tokens 
); 

$sql = "SELECT * FROM tbl_address WHERE address LIKE'%"; 
$sql .= implode("%' OR address LIKE '%", $keyword_tokens) . "'"; 

// query and collect the result to $result 
// before inserting to $result, check if the id exists in $result. 
// if yes, skip. 

return $result; 

Ponadto, należy również zdać link zasobów db do funkcji mysqli_real_escape_string() ...

+0

Tęskniłeś za ciągiem pojedynczych cudzysłowów dla '$ sql' chociaż. – Raptor

+1

Masz rację. Wszystko już dodane :) – arraintxo

+0

To nie działa; mówi, że mam błąd sql; – Eenvincible

1

Złóż pojedyncze zapytanie

$keywordary = explode(',', $keywords); 
foreach($keywordary as $keyword) { 
    $keys = trim($keyword); 
    $other .=" or address like '%$keys%'"; 
} 
$sql = "SELECT * FROM tbl_address WHERE address LIKE'%$keyword%' $other"; 

execute query; 
return $result; 
+1

Czy nie powinno to być '$ other. =" 'Zamiast' $ other = "' wewnątrz twojej pętli? W przeciwnym razie anulujesz klauzulę 'lub' w każdej pętli. – TheCarver

1

Spróbuj gdzie w klauzuli:

$keyword = (array)explode(',', $keywords); 
for($i=0;$i=count($keyword);$i++){ 
    $keyword[$i]=mysqli_real_escape_string(trim($keyword[$i]),'\'" '); 
} 
//This is what I suggest. 
$query='SELECT * FROM tbl_address WHERE address IN ("'.implode('","',$keyword).'")'; 

powodzeniem przetestowany na MySQL 5.1.

Powiązane problemy