У меня есть строка с запятыми. Например:
$keywords = 'keyword1, keyword2, keyword3';
Моя схема таблицы, названная tbl_address
, подобна этой (упрощенной):
id INT(11) PRIMARY KEY, AUTO INCREMENT address VARCHAR(250) NOT NULL
Предположим, что мне нужно использовать MySQLi
в PHP (а не PDO
).
Вот мой нынешний подход:
$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;
Этот подход работает, но неэффективен в производительности. Если есть много ключевых слов, это вызовет много запросов.
Мой вопрос в том, есть ли лучший способ достичь той же цели? т.е. какой самый простой способ вернуть все записи с адресом, содержащим ЛЮБОЕ из ключевых слов?
Простой REGEXP
может быть тем, что вам нужно. Вам нужно будет проверить, насколько он эффективен для вас.
SELECT * FROM tbl_address WHERE field REGEXP 'keyword1|keyword2|keyword3';
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 | +---------+----------+
Вам нужно только «OR», ничего больше …
<?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: просто чтобы быть уверенным, что вы также обрезаете ключевые слова
<?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;
Кроме того, вы также должны передать ссылку ресурса db на mysqli_real_escape_string()
…
Попробуйте предложение WHERE IN:
$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).'")';
Успешно протестирован на MySQL 5.1.
Сделать одиночный запрос
$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;
Лучший способ – использовать полнотекстовый поиск.
http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html
если вы не хотите использовать полный текст, вы можете использовать OR в состоянии WHERE
SELECT * FROM tbl_address WHERE address LIKE '%$keyword%' OR adress LIKE '%$keyword2%'
Лучший способ – это просто создать предложение WHERE WHERE и добавить его к запросу и запустить его один раз.
$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;
Привет, создайте запрос с объединением и выполните в конце цикла
$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. }
Выполните запрос здесь.