显示通过搜索查询找到的列

Display which column was found with search query

提问人:Born2DoubleUp 提问时间:3/7/2017 最后编辑:Born2DoubleUp 更新时间:3/7/2017 访问量:121

问:

我有一段简单的代码,可以从我的一个数据库表中的所有行中搜索三列。表名是“articles”,我正在搜索的 3 列是“Title、Description 和 Tags”。目前,我搜索一个单词或短语,它向我显示了结果,我想知道的是,是否有办法让我显示找到 3 列中的哪一列有结果。我是否必须对作为结果返回的每一行运行单独的查询,或者是否有更简单的方法?我在下面包含了我的代码片段。

$query = $_GET['q'];
$sql = "SELECT * FROM articles WHERE (`title` LIKE '%".$query."%') OR (`description` LIKE '%".$query."%') OR (`tags` LIKE '%".$query."%') ORDER BY dateadded";
$query = $db->query($sql);
while($row = $query->fetch_assoc()) {
display 
} 
PHP MySQL 搜索

评论

3赞 Strawberry 3/7/2017
存在称为标签的列通常是设计不佳的征兆。
1赞 Strawberry 3/7/2017
您可以使用 UNION 来解决您的问题
0赞 Born2DoubleUp 3/7/2017
是的,我知道列名并不完美。我重命名了它们以使事情变得简单,以便更容易提出我的问题。

答:

1赞 jeroen 3/7/2017 #1

一个快速的解决方法是使用您的条件选择一些其他列:

SELECT *,
  IF(`title` LIKE '%".$query."%',       1, 0)  AS conditionTitle,
  IF(`description` LIKE '%".$query."%', 1, 0)  AS conditionDescription,
  IF(`tags` LIKE '%".$query."%',        1, 0)  AS conditionTags
FROM articles 
WHERE (`title` LIKE '%".$query."%')
  OR (`description` LIKE '%".$query."%')
  OR (`tags` LIKE '%".$query."%') 
ORDER BY dateadded";

现在,您可以检查每行中这些附加列的值,以检查是否在该特定字段中找到了。$query

请注意,您应该使用准备好的语句,因为现在您可能遇到 sql 注入问题。

评论

0赞 Born2DoubleUp 3/7/2017
我必须多研究一下你的代码,因为我不确定它在做什么。哈哈,当谈到 php 和 mysql 时,我仍然很青涩,试图一天一天地自学所有这些东西,但这是出于建议,我一定会研究它!
0赞 jeroen 3/7/2017
@Born2DoubleUp 您将在找到的每一行中增加 3 列,这些列的值为 或(1 和 0 当然会方便移动......只需运行它,例如phpMyAdmin即可查看结果。yepnope
0赞 jeroen 3/7/2017
@Born2DoubleUp 我已切换到整数输出以使检查更容易。
0赞 spencer7593 3/7/2017 #2

一种替代方法是测试表达式中的条件,即 SELECT 列表。

我认为最简单的解释方法是举例说明。但是我不能凭良心发布易受 SQL 注入攻击的示例代码。

当前查询:

 SELECT a.*
   FROM articles
  WHERE a.`title`       LIKE CONCAT('%', ? ,'%')
     OR a.`description` LIKE CONCAT('%', ? ,'%')
     OR a.`tags`        LIKE CONCAT('%', ? ,'%')
  ORDER
     BY a.dateadded

对于当前查询,我们可以将表达式添加到 SELECT 列表。举个例子:

 SELECT IF( a.`title`       LIKE CONCAT('%', ? ,'%') ,1,0) AS match_in_title 
      , IF( a.`description` LIKE CONCAT('%', ? ,'%') ,1,0) AS match_in_description
      , IF( a.`tags`        LIKE CONCAT('%', ? ,'%') ,1,0) AS match_in_tags
      , a.*
   FROM articles
  WHERE a.`title`       LIKE CONCAT('%', ? ,'%')
     OR a.`description` LIKE CONCAT('%', ? ,'%')
     OR a.`tags`        LIKE CONCAT('%', ? ,'%')
  ORDER
     BY a.dateadded

对于返回的每一行,将计算 SELECT 列表中的表达式。条件检验 ( comparison) 的计算结果为 TRUE、FALSE 或 NULL。MySQL函数将第一个参数评估为布尔值,如果为真,它将返回第二个参数,elise返回第三个参数。LIKEIF

在此示例中,如果存在匹配项,则表达式将返回 a。否则,它将返回 .对于我们可以返回的值,还有很多其他选择。我们还可以将条件组合到单个表达式中,以返回单个值。10

并且有很多可能的表达式可以包含条件测试。我刚刚使用了MySQL函数。更符合 ANSI 标准的表达式可以使用,例如IFCASE

 SELECT CASE WHEN a.`title`       LIKE CONCAT('%', ? ,'%') 
             THEN 1
             ELSE 0
        END AS match_in_title
0赞 Raymond Nijland 3/7/2017 #3

这样的事情应该有效。 使用名为 search_articles 和 UNION ALL 的交付表,将 SELECT 查询组合在一起。

SELECT
  search_column
, *
FROM (
  SELECT
   'title' AS search_column
   , *
  FROM
   artices
  WHERE
   title LIKE '%query%'

  UNION ALL 

  SELECT
   'description' AS search_column
   , *
  FROM
   artices
  WHERE
   description LIKE '%query%' 

  UNION ALL 

  SELECT
   'tags' AS search_column
   , *
  FROM
   artices
  WHERE
   tags LIKE '%query%'  
)
 AS
   search_articles

评论

0赞 spencer7593 3/7/2017
请注意,此查询可能会多次返回同一行。例如,如果行在 和 上都“匹配”。articlestagstitle
0赞 Raymond Nijland 3/7/2017
@spencer7593为 true,则主题启动器应删除关键字 ALL 在所有 UNIONS 之后删除重复项
0赞 spencer7593 3/7/2017
使用 in 代替 of 并不能真正解决这个问题,因为返回的值在查询之间是不同的,而 .唯一的排序操作将保留两行。UNIONUNION ALLsearch_column'title''tags'