2013-04-16 204 views
10

我有一个包含逗号分隔关键字的字符串。例如:MySQL和PHP:多关键字搜索

$keywords = 'keyword1, keyword2, keyword3'; 

我的表架构,命名为tbl_address是这样(简化):

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

假设我在PHP中使用MySQLi(不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; 

这种方法有效,但在性能上效率低下。如果有很多关键字,它会做很多查询。

我的问题是,是否有更好的方法来实现相同的目标?即用包含任何关键字的地址返回所有记录的最简单方法是什么?

+0

这可以帮助你:http:// stackoverflow。com/a/9736386/1983854 – fedorqui

+0

结合“LIKE”和“IN”:http://stackoverflow.com/questions/1865353/combining-like-and-in-for-sql-server – Chris

+2

@Shivian认真,为什么didn'你用我的REGEXP单线? – Jimbo

回答

17

一个简单的REGEXP可能是你所追求的。你必须检查自己的效率。

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

+1

+1,这正是我所寻找的,我也学到了一个新的'MySQL'字符串函数! –

+1

优秀的答案,这帮助我解决了一周的研究,并帮助我跳过了我的问题的30%:) – 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

只是一个警告与这种方法。不能使用LIKE语法,并且不会修剪关键字... – arraintxo

0

刚刚创建的搜索字符串的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; 
0

嗨创建工会查询,并在循环

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

年底执行此执行查询。

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; 

编辑:只是要确保你也修剪关键字

<?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()函数...

+0

尽管您错过了“$ sql”的尾部单引号。 – Raptor

+1

你说得对。 Allready added too :) – arraintxo

+0

这不起作用;它说我有SQL错误; – Eenvincible

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

在循环中,这不是'$ other。=“'而不是'$ other =”'吗?否则,你将取消每个循环中的'或'子句。 – TheCarver

1

尝试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测试成功。