【问题标题】:search customer in database with different number of search keys使用不同数量的搜索键在数据库中搜索客户
【发布时间】:2017-04-12 14:09:58
【问题描述】:

找到了其他一些帖子,但没有一个对我有真正的帮助(也许我太笨了,无法搜索)。甚至在键入此内容时 Similar Questions 块也无济于事。

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

在一个 php 应用程序上,我有一个输入字段,它通过 AJAX 查询 php 脚本以搜索数据库。如果只给出 1 个搜索词,例如名字,则此字段有效。当我尝试 2 或 3 个搜索词时,我不知道如何查询数据库。

请帮助我如何查询我的数据库(大约有 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:我的母语不是英语,但我已经尽力了。


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


~~编辑~~

我想出的东西,但没有用:

$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

【问题讨论】:

  • 如果你从你的 AJAX 传递一些合理的组织良好的参数,这会让你的喜欢变得容易得多.目前,您如何区分名字、姓氏或城市?
  • 这会很好也很容易,但我无法控制用户。只有一个输入字段,用户必须能够以您能想到的任何方式搜索名字、姓氏和城市。

标签: php mysql database search


【解决方案1】:

感谢 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);
        }

    }

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

【讨论】:

    【解决方案2】:

    你需要循环 $keys 来扩展你的查询

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

    然后分别绑定每个参数,每个 ?

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

    【讨论】:

    • 你的意思是突然从mysqli语法切换到PDO语法吗?
    • 谢谢。这实际上让我走上了正轨。
    • @user2129866 你接受了这个,但这不是一个正确的答案。这不会帮助其他有类似问题的人,并将其视为可接受的答案
    • true @RiggsFolly 他给了我解决问题的想法,但我必须等待 2 天才能接受我自己的答案:(
    猜你喜欢
    • 2018-04-27
    • 1970-01-01
    • 2019-02-20
    • 1970-01-01
    • 2017-03-17
    • 2014-09-02
    • 2016-12-01
    • 2014-04-14
    • 1970-01-01
    相关资源
    最近更新 更多