Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php MySQL中的复杂搜索_Php_Mysql_Sql - Fatal编程技术网

Php MySQL中的复杂搜索

Php MySQL中的复杂搜索,php,mysql,sql,Php,Mysql,Sql,我需要在MySQL数据库中进行复杂的搜索。我想用一个查询来解决这个问题,以避免PHP代码中的大部分更改 这就是它的工作原理: 用户在搜索字段中输入文本 系统搜索关键字 系统在名称中搜索 系统在文本中搜索 系统按类别进行搜索 如果系统在关键字:1点、名称:1点、文本:1点/提及、类别:1点中找到匹配项 得分最多的用户排名第一,得分第二多的用户排名第二,依此类推 使用IF,ELSE,CASE,WHEN这个查询可行吗?我从来没有做过这种复杂的搜索。问题更大,我看了两张表: TABLE USERS: i

我需要在MySQL数据库中进行复杂的搜索。我想用一个查询来解决这个问题,以避免PHP代码中的大部分更改

这就是它的工作原理:

  • 用户在搜索字段中输入文本
  • 系统搜索关键字
  • 系统在名称中搜索
  • 系统在文本中搜索
  • 系统按类别进行搜索
  • 如果系统在关键字:1点、名称:1点、文本:1点/提及、类别:1点中找到匹配项

    得分最多的用户排名第一,得分第二多的用户排名第二,依此类推

    使用IF,ELSE,CASE,WHEN这个查询可行吗?我从来没有做过这种复杂的搜索。问题更大,我看了两张表:

    TABLE USERS:
    id    |    name    |    lastname    |    category    |    keywords    |    text    |
    TABLE PAGES:
    id    |    user_id    |
    

    我需要列出表“用户”,但如果用户有自己的页面,则首先显示有“页面”的用户,然后再列出没有“页面”的其他用户。

    您可以通过简单的
    按顺序执行此操作。下面是一个使用类似于
    搜索词的示例:

    select u.*
    from users u
    order by ((keywords like '%@SEARCHTERM%') +
              (name like '%@SEARCHTERM%') +
              (text like '%@SEARCHTERM%') +
              (category like '%@SEARCHTERM%')
             ) desc;
    
    要获取有关页面的信息,请加入:

    select u.*
    from users u left outer join
         (select user_id, count(*) as numpages
          from pages p
          group by user_id
         ) p
         on u.id = p.user_id
    order by (p.numages > 0) desc,
             ((keywords like '%@SEARCHTERM%') +
              (name like '%@SEARCHTERM%') +
              (text like '%@SEARCHTERM%') +
              (category like '%@SEARCHTERM%')
             ) desc;
    
    orderby
    中的条件使用MySQL将布尔值视为数字的事实,其中
    1
    表示true,
    0
    表示false。您可以将它们相加以获得匹配的总数

    本例使用类似于
    。您可以使用
    match。如果您更喜欢全文搜索,请使用

    编辑:

    如果您担心列可能包含
    NULL
    ,请使用
    coalesce()

    是的,有可能


    我认为提供的规范意味着,如果在
    关键字
    列中未找到匹配项,则分数为0。如果在
    关键字
    中找到匹配项,但在
    名称
    列中未找到匹配项,则分数为1。如果在
    关键字
    名称
    列中找到匹配项,但在
    文本
    列中未找到匹配项,则得分为2。等等(我可能误解了规范,将更多的含义归因于列出匹配项的顺序,以及“如果它在”…如果在
    名称中找到匹配项,而不是在
    关键字中找到匹配项,那么我们不会说“它匹配名称”。)

    另一种方法是使用MySQL
    IF()
    函数

    SELECT t.id
         , t.name
         , t.lastname
         , t.category
         , t.keywords
         , t.text
         , IF(t.keywords LIKE '%text%'
             ,IF(t.name LIKE '%text%'
                ,IF(t.text LIKE '%text%'
                   ,IF(t.category LIKE '%text%'
                      ,4
                      ,3)
                   ,2)
                ,1)
             ,0) AS `points`
      FROM `users` t
      LEFT
      JOIN ( SELECT p.user_id FROM pages p GROUP BY p.user_id ) q
        ON q.user_id = t.id
    HAVING `points` > 0
     ORDER
        BY `points` DESC, q.user_id IS NULL DESC
    
    可以使用ANSI标准
    CASE
    表达式实现等效

    SELECT t.id
         , t.name
         , t.lastname
         , t.category
         , t.keywords
         , t.text
         , CASE WHEN t.keywords LIKE '%text%' THEN
             CASE WHEN t.name     LIKE '%text%' THEN
               CASE WHEN t.text     LIKE '%text%' THEN
                 CASE WHEN t.category LIKE '%text%' THEN
                   4
                 ELSE 3 END
               ELSE 2 END
             ELSE 1 END
           ELSE 0 END AS `points`
      FROM `users`
      LEFT
      JOIN ( SELECT p.user_id FROM pages p GROUP BY p.user_id ) q
        ON q.user_id = t.id
    HAVING `points` > 0
     ORDER
        BY `points` DESC, q.user_id IS NULL DESC
    

    跟进

    如果规范意味着如果用户提供的文本出现在四列中的任何一列中,并且每行的“点数”总数是该行中匹配的列数,那么我们可以使用简单的条件测试添加,而不是嵌套它们

    SELECT t.id
         , t.name
         , t.lastname
         , t.category
         , t.keywords
         , t.text
         , IF(t.keywords LIKE '%text%',1,0) +
           IF(t.name     LIKE '%text%',1,0) +
           IF(t.text     LIKE '%text%',1,0) +
           IF(t.category LIKE '%text%',1,0) AS `points`
      FROM `users` t
      LEFT
      JOIN ( SELECT p.user_id FROM pages p GROUP BY p.user_id ) q
        ON q.user_id = t.id
    HAVING `points` > 0 WHERE 
     ORDER BY `points` DESC, q.user_id IS NULL DESC
    

    此查询(与前面的查询一样)将首先列出
    点的计算值最高的用户,然后根据
    页面
    表中是否有匹配行列出。(如果
    q.user\u id
    页面中的
    行与
    id
    中的
    users
    匹配,则表达式
    q.user\u id
    将为空,如果存在匹配,则表达式将为非空。因此,按表达式“
    q.user\u id为空
    ”排序在没有
    页面的用户之前,您是否会对使用
    页面的用户进行排序?

    您研究过MySQL中的全文搜索功能集吗?它可能会产生您需要的结果。这几乎肯定是可能的,因为子查询本质上意味着您可以生成虚拟临时表,因此您可以慢慢构建结果呃,这可能不是特别有效。为什么需要避免使用PHP来处理结果?可能是联合查询?
    选择1作为点,“名称”作为源…联合所有选择2作为点,“关键字”作为源…等等。
    ?我在数据库中调查全文。我不想有太多sql查询,在PHP中使用“if”/“else”切换和计数。当前搜索页面很大,我需要更改所有内容。唯一的解决方案是只替换PHP中用于生成单词和字符串清理的查询和输入函数。我可能误解了规范。我将意义归因于搜索匹配列的特定顺序。我还将我归因于与规范“if is all in”一致。我认为这意味着,如果上一次检查成功,我们将加1分,否则,如果行之前没有匹配,我们将不会加1分。(如果我们希望为每个匹配的分数加1分,则派生
    分的表达式可以很容易地更改)不,这是额外的,但不是我需要的解决方案。请重新阅读规范。评分是一个很好的补充,但按照相同的顺序,我必须搜索数据库和用户谁有最多的分数,页面放在第一位,其他人放在下面。谢谢!没有特别的“顺序”数据库需要搜索的行。行满足谓词并返回,或不满足谓词并不返回。
    orderby
    子句指定返回行的顺序。注意:如果我们保证“搜索”列(使用LIKE运算符),这是很好的不为NULL。在更一般的情况下,我们希望预测
    NULL
    值将如何影响“points”表达式。为了适当地处理NULL值,我们可以按照
    IFNULL(category,”)这样做,如“%t%”
    IF(category,如“%t%”,1,0)
    @spencer7593…这是一个很好的观点。我编辑了答案。
    SELECT t.id
         , t.name
         , t.lastname
         , t.category
         , t.keywords
         , t.text
         , IF(t.keywords LIKE '%text%',1,0) +
           IF(t.name     LIKE '%text%',1,0) +
           IF(t.text     LIKE '%text%',1,0) +
           IF(t.category LIKE '%text%',1,0) AS `points`
      FROM `users` t
      LEFT
      JOIN ( SELECT p.user_id FROM pages p GROUP BY p.user_id ) q
        ON q.user_id = t.id
    HAVING `points` > 0 WHERE 
     ORDER BY `points` DESC, q.user_id IS NULL DESC