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

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

$keywords = 'keyword1, keyword2, keyword3';

Схема My Table, названная 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;

Этот подход работает, но неэффективен по производительности. Если есть много ключевых слов, это вызовет много запросов.

Мой вопрос: есть ли лучший способ достичь той же цели? то есть самый простой способ вернуть все записи с адресом, содержащим ЛЮБОЕ из ключевых слов?

Ответ 1

Простым REGEXP может быть то, что вам нужно. Вам нужно будет проверить, насколько он эффективен для вас.

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

Ответ 2

 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     |
 +---------+----------+

Ответ 3

Вам нужен только "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()...

Ответ 4

Сделать одиночный запрос

$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;

Ответ 5

Попробуйте предложение 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.

Ответ 6

Лучший способ - использовать полнотекстовый поиск.

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%'

Ответ 7

Лучший способ - просто создать предложение 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;

Ответ 8

Привет, создайте запрос с объединением и выполните в конце цикла

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

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