Intereting Posts
Symfony – Использование внешних соединений с доктриной ORM Delphi TIdhttp Post JSON? Как я могу использовать транзакцию db в laravel? Получение значения параметра без отправки формы Я NetBeans, могу ли я каким-либо образом сохранить отпечаток ключа RSA на удаленном сервере или не подтвердить NetBeans ключ до принятия решения? Передача динамических данных в загрузочный модальный Левый Присоединение первичного ключа к нормальному столбцу вызывает хаос Как создать новую пустую Eloquent Collection в Laravel 4 Невозможно выполнить PHP-скрипт с помощью PHP exec Как получить текст привязки с помощью DomDocument? Как отправить изображение на Twitter с помощью php? Динамическое изменение имени столбца в инструкции PDO Форма Symfony2 – от многих до многих, поскольку текст вызывает ошибки Буферизация вывода PHP в командной строке Ошибка построения: фатальная ошибка: pcre.h: нет такого файла или каталога

MySQL и PHP: поиск по нескольким ключевым словам

У меня есть строка с запятыми. Например:

$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. } 

Выполните запрос здесь.