使用不同数量的搜索键在数据库中搜索客户

时间:2017-04-12 14:09:58

标签: php mysql database search

发现了一些其他帖子,但没有一个真正帮助过我(也许我对搜索太愚蠢了)。键入此内容时,即使是Similar Questions块也无济于事。

这是我的问题: 我有一个包含4列的mysql数据库:id,first-name,last-name,city

在php应用程序中,我得到一个输入字段,通过AJAX查询php脚本来搜索数据库。如果仅给出1个搜索词,则此字段有效,如名字。一旦我尝试2或3个搜索词,我就不知道如何查询db。

请帮我查询我的数据库(大约有20,000行)。 一些搜索示例: Thomas Boston Michael Smith New York Doe, Jane Orlando, Michael 预期结果是包含任何搜索项的所有行。最好的方法是按相似性排序(大多数术语首先发现)。使用DIFFERENCE()也会很好,但我的脚本是德语....

我已阅读有关全文搜索的内容,但不知道如何执行此操作。

这是我当前的查询代码(1个搜索词):

$key = $_GET['key'];
//Here will be something to filter all non numbers/letters and change them to a space for $key
$keys = explode(" ",$key); //$keys is not in use yet
$prep_stmt = "
SELECT 
    id, last-name, first-name, city 
FROM 
    customers 
WHERE 
    last-name LIKE concat('%', ? ,'%') OR
    first-name LIKE concat('%', ? ,'%')  OR
    city LIKE concat('%', ? ,'%') 
ORDER BY 
    last-name ASC";
$stmt = $mysqli->prepare($prep_stmt);
$stmt->bind_param('sss', $key, $key, $key);

关于安全性:此代码在内部环境中运行。因此,安全不是最重要的优先事项。

PS:我不是英国人,但我尽力了。

我找到的东西,但没有帮助:

~~ EDIT ~~

我想出的东西,但没有工作:

$key = trim(preg_replace( '/\s+/', ' ', preg_replace("/[^[:alnum:][:space:]]/u", ' ', $key)));

SELECT
    id, last-name, first-name, city 
FROM
    customers
WHERE
    last-name LIKE concat('%', REPLACE( ? ,' ','%') ,'%') OR
    first-name LIKE concat('%', REPLACE( ? ,' ','%') ,'%') OR
    city LIKE concat('%', REPLACE( ? ,' ','%') ,'%')                
ORDER BY
    name ASC

2 个答案:

答案 0 :(得分:0)

感谢Rogier Bruggeman,我知道如何解决我的问题。这就是我解决它的方法:

$key = $_GET['key'];
$key = trim(preg_replace( '/\s+/', ' ', preg_replace("/[^[:alnum:][:space:]]/u", ' ', $key)));
$keys = explode(" ",$key);
$key_num = count($keys);
if(NOT RELEVANT == RELEVANT){
    NOT RELEVANT
} else {
    //prepare statement
    $prep_stmt = "SELECT id  FROM customers WHERE ";
    if($key_num == 1){
        $prep_stmt .= "
            lastname LIKE ? OR
            firstame LIKE ? OR
            zip LIKE ? OR
            city LIKE ?
        ORDER BY
            lastname ASC";
        $stmt = $mysqli->prepare($prep_stmt);
        $key = '%' . $key . '%';
        $stmt->bind_param('ssss', $key, $key, $key, $key);
    } else {
        $p = 0;
        foreach($keys as $v){
            if($p <> 0){
                $prep_stmt .= " AND ";
            }
            $prep_stmt .= "(lastname LIKE ? OR firstname LIKE ? OR zip LIKE ? OR city LIKE ? )";
            $p++;
        }
        $prep_stmt .= " ORDER BY name ASC";
        $stmt = $mysqli->prepare($prep_stmt);
        switch($key_num){
            case 2:
                $keys[0] = '%' . $keys[0] . '%';
                $keys[1] = '%' . $keys[1] . '%';
                $stmt->bind_param('ssssssss', $keys[0], $keys[0], $keys[0], $keys[0], $keys[1], $keys[1], $keys[1], $keys[1]);
                break;
            case 3:
                $keys[0] = '%' . $keys[0] . '%';
                $keys[1] = '%' . $keys[1] . '%';
                $keys[2] = '%' . $keys[2] . '%';
                $stmt->bind_param('ssssssssssss', $keys[0], $keys[0], $keys[0], $keys[0], $keys[1], $keys[1], $keys[1], $keys[1], $keys[2], $keys[2], $keys[2], $keys[2]);
                break;
            case 4:
                $keys[0] = '%' . $keys[0] . '%';
                $keys[1] = '%' . $keys[1] . '%';
                $keys[2] = '%' . $keys[2] . '%';
                $keys[3] = '%' . $keys[3] . '%';
                $stmt->bind_param('ssssssssssssssss', $keys[0], $keys[0], $keys[0], $keys[0], $keys[1], $keys[1], $keys[1], $keys[1], $keys[2], $keys[2], $keys[2], $keys[2], $keys[3], $keys[3], $keys[3], $keys[3]);
                break;
            case 5:
                $keys[0] = '%' . $keys[0] . '%';
                $keys[1] = '%' . $keys[1] . '%';
                $keys[2] = '%' . $keys[2] . '%';
                $keys[3] = '%' . $keys[3] . '%';
                $keys[4] = '%' . $keys[4] . '%';
                $stmt->bind_param('ssssssssssssssssssss', $keys[0], $keys[0], $keys[0], $keys[0], $keys[1], $keys[1], $keys[1], $keys[1], $keys[2], $keys[2], $keys[2], $keys[2], $keys[3], $keys[3], $keys[3], $keys[3], $keys[4], $keys[4], $keys[4], $keys[4]);
                break;
            case 6:
                $keys[0] = '%' . $keys[0] . '%';
                $keys[1] = '%' . $keys[1] . '%';
                $keys[2] = '%' . $keys[2] . '%';
                $keys[3] = '%' . $keys[3] . '%';
                $keys[4] = '%' . $keys[4] . '%';
                $keys[5] = '%' . $keys[5] . '%';
                $stmt->bind_param('ssssssssssssssssssssssss', $keys[0], $keys[0], $keys[0], $keys[0], $keys[1], $keys[1], $keys[1], $keys[1], $keys[2], $keys[2], $keys[2], $keys[2], $keys[3], $keys[3], $keys[3], $keys[3], $keys[4], $keys[4], $keys[4], $keys[4], $keys[5], $keys[5], $keys[5], $keys[5]);
                break;
            default:
                $stmt = "SELECT id FROM customer WHERE 1 LIKE 2";
                $stmt = $mysqli->prepare($prep_stmt);
        }

    }

它有点脏,但它有效。真的很脏,我default

中的switch

答案 1 :(得分:-1)

您需要循环$键以扩展查询

$prep_stmt = "
    SELECT 
        id, last-name, first-name, city 
    FROM 
        customers 
    WHERE ";

foreach($key as $v)
{
    $prep_stmt .= " OR last-name LIKE concat('%'%') OR
    first-name LIKE concat('%', ? ,'%')  OR
    city LIKE concat('%', ? ,'%') OR  " ;
}
$prep_stmt .= " 1 
ORDER BY 
    last-name ASC
";

然后分别绑定每个param,每个一次?

$p = 1; foreach($key as $v) { $stmt->bindParam($p++,$v); $stmt->bindParam($p++,$v); $stmt->bindParam($p++,$v); }