【问题标题】:PDO search query, make it like android contacts searchPDO搜索查询,让它像android联系人搜索
【发布时间】:2014-11-03 20:45:02
【问题描述】:

我尝试使用 LIKE 查询在我的小工具中实现搜索。

现在我有了这个新要求,我必须像 Android 搜索一样进行此搜索..

查询:

$stmt = $conn->prepare("SELECT ROOM, GUEST_NAME, GUEST_FIRST_NAME, CONFIRMATION_NO, DEPARTURE, PWD FROM RESERVATION_GENERAL_2 WHERE LOWER(GUEST_FIRST_NAME) LIKE ? OR LOWER(GUEST_NAME) LIKE ?");
$stmt->execute(array('%'.strtolower($searchFilter).'%','%'.strtolower($searchFilter).'%' ));

假设我在数据库中有一个字符串Syed Haider Hassan 如果我使用给定的查询在数据库表中搜索san,它将找到我上面的字符串。 因此,如果我在字符串内部或任何地方放置任何匹配的内容,它将得到这个字符串,

但我想要的是,当我在数据库中搜索 HaiHasSy 它应该得到我这个字符串,但如果我搜索 san 甚至 assan,查询不应该显示我这个字符串。 意味着如果我搜索它必须使用startwith 进行搜索,而不是从中间搜索。 我认为如果我从开头删除% 可能是可能的,但问题是查询只会在 Syed 上看到 startwith,我希望它对每个单词都应用 startwith,因为单词用空格分隔。搜索SyedHaiderHassan不同..

我知道我上面试图解释的内容很混乱,主要是因为我的英语不好。 但简单来说,如果你有 Android 手机,我有 Galaxy S4,在你的通讯录中搜索任何名字。如果你从单词的中间搜索它不会搜索,但如果你从单词的开头搜索它会搜索,但事实并非如此。如果您的联系人姓名是由空格分隔的两个单词的组合 然后它还会检查第二个单词的第一个字母。

我希望我很清楚,但我不知道如何实现该查询。如果有人可以将我的查询更新为这个新的搜索条件,我将非常高兴。

========================================

更新

好的,我按照其中一个答案中的建议使用 try catch 尝试了匹配,但出现此错误。

这是我尝试过的代码。

$search_words = "+" . str_replace (" ", "* +", $searchFilter )."*";
        try {
            $stmt = $conn->prepare("SELECT ROOM, GUEST_NAME, GUEST_FIRST_NAME, CONFIRMATION_NO, DEPARTURE, PWD FROM RESERVATION_GENERAL_2 WHERE MATCH (GUEST_FIRST_NAME, GUEST_NAME) against (:SEARCH in boolean mode)");
            $stmt->bindValue(':SEARCH', $search_words, PDO::PARAM_STR);
            $stmt->execute();

        }
        catch(PDOException $e){
            echo 'ERROR: ' . $e->getMessage();
        }

有什么办法解决吗?

====================================

更新 2

好的,我只是把事实放在这里。 这是我的表结构。

如果我使用 like 和通配符 %%,它会从名字中间开始搜索。

让我们看看截图中突出显示的名称,突出显示的名称是Lukasz Henryk。 如果我使用 %enry% 之类的通配符进行搜索,它会找到我这一行。 但我不希望这样,我希望搜索应该以名称开头的单词。 例如,如果我搜索LukHenHe 甚至H,它应该会找到我这一行。表示起始字母很重要,如果起始字母不匹配,请不要给我行。

我也尝试了类似Henr% 这样的通配符查询,但它不起作用,因为它只适用于Luk%,它将整个列视为单个字符串。

有没有办法告诉查询在空格后搜索起始字母?

请有人帮助我。

【问题讨论】:

    标签: php android sql search pdo


    【解决方案1】:

    您可以使用 MySQL:s MATCH AGAINST。请记住,您必须创建一个包含 GUEST_FIRST_NAME 和 GUEST_NAME(按此顺序)的 FULLTEXT 索引。

    只是一个例子:

    $string = "syed haider";
    $search_words = "+" . str_replace (" ", "* +", $string )."*";
    
    $query = "SELECT ROOM, GUEST_NAME, GUEST_FIRST_NAME, CONFIRMATION_NO, DEPARTURE, PWD FROM RESERVATION_GENERAL_2 WHERE MATCH (GUEST_FIRST_NAME) against ('$search_words' in boolean mode) OR MATCH (GUEST_NAME) against ('$search_words' in boolean mode)";
    
    // SELECT ROOM, GUEST_NAME, GUEST_FIRST_NAME, CONFIRMATION_NO, DEPARTURE, PWD FROM RESERVATION_GENERAL_2 WHERE MATCH (GUEST_FIRST_NAME) against ('+syed* +haider*' in boolean mode) OR MATCH (GUEST_NAME) against ('+syed* +haider*' in boolean mode)
    

    【讨论】:

    • 你能不能让这个查询在 pdo 中工作。如果可能的话更新我的查询。我不擅长数据库查询..
    【解决方案2】:

    你试过 mysql regexp (rlike) 吗?

    表设置:

    CREATE TABLE `user` (
      `name` varchar(50) NOT NULL DEFAULT ''
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    INSERT INTO `user` (`name`)
    VALUES
        ('Syed Haider Hassan');
    

    查询:

    select * from user where name rlike '[[:<:]]Hass'
    

    返回:

    name
    Syed Haider Hassan
    

    不匹配的查询:

    select * from user where name rlike '[[:<:]]san'
    

    返回:

    name
    

    【讨论】:

    • Rlike 可能真的很慢并且会弄乱索引。
    【解决方案3】:

    您的问题来自搜索字符串 ($search_words = "+" .str_replace (" ", "* +", $searchFilter )."*";),导致关系运算符为 "+,-, 等.",这就是为什么您需要首先查看完整的查询。

    执行以下步骤:

    1. 回显您的 sql 查询并尝试在某些 MySql GUI(例如 Navicat)中执行,以确保您的查询没有错误。
    2. 确保 GUEST_FIRST_NAME、GUEST_NAME 字段索引为“全文”。为此,您需要执行“ALTER TABLE RESERVATION_GENERAL_2 添加全文索引name_index (GUEST_FIRST_NAME, GUEST_NAME) ;"

    试试这个步骤,然后告诉我。

    【讨论】:

      【解决方案4】:

      正如其他人所说,全文索引是要走的路,这就是您希望查询看起来的样子,+ 使所有需要的单词都将其排除在外,以便查找任何单词。您不能将" 双引号与* 通配符一起使用,这是合理的,因为双引号表示exact 字。使用通配符时不能这样。 (或者至少我还没有找到方法)

      SELECT
          ROOM,
          GUEST_NAME,
          GUEST_FIRST_NAME,
          CONFIRMATION_NO,
          DEPARTURE,
          PWD
      FROM
          RESERVATION_GENERAL_2
      WHERE
          MATCH(GUEST_NAME, GUEST_FIRST_NAME)
      AGAINST
          ( '+word* +word2*' IN BOOLEAN MODE )
      

      基本上

        $search_words = '';
       foreach( explode(' ', $search) as $words ){
             $search_words .= '+'.$word.'* ';
       }
      

      ...
      WHERE
          MATCH(GUEST_NAME, GUEST_FIRST_NAME)
      AGAINST
          ( :search_words IN BOOLEAN MODE )
      
       $stmt->bindValue(':search_words', $search_words, PDO::PARAM_STR);
      

      等等……

      但是你必须有一个全文索引,在这种情况下是一个在GUEST_NAME, GUEST_FIRST_NAME 上的复合索引。

      另请参阅

      MySQL Full Text Search Mystery

      【讨论】:

        猜你喜欢
        • 2014-11-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-28
        • 1970-01-01
        • 2015-01-10
        • 1970-01-01
        • 2013-09-07
        相关资源
        最近更新 更多