【问题标题】:Display which column was found with search query显示通过搜索查询找到了哪一列
【发布时间】:2017-03-07 23:57:06
【问题描述】:

我有一段简单的代码,它从我的一个数据库表的所有行中搜索三列。表名是“文章”,我正在搜索的 3 列是“标题、描述和标签”。目前我搜索一个单词或短语,它会显示结果,我想知道是否有办法让我显示在结果中找到了 3 列中的哪一列。我是否必须对作为结果返回的每一行运行单独的查询,还是有更简单的方法?我在下面包含了我的代码的 sn-p。

$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 
} 

【问题讨论】:

  • 标签列的存在通常表明设计不佳。
  • 您可以使用 UNION 来解决您的问题
  • 是的,我知道列名并不完美。我重命名了它们以使事情变得简单,以便更容易提出我的问题。

标签: php mysql search


【解决方案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 注入问题。

【讨论】:

  • 我将不得不更多地研究您的代码,因为我不确定它在做什么。大声笑,当谈到 php 和 mysql 时,我仍然是绿色的,试图一天一次地自学所有这些东西,但那是我一定会研究它的建议!
  • @Born2DoubleUp 您将在您找到的每一行中添加 3 列,这些列的值将是 yepnope(1 和 0 当然移动方便......) .只需在例如 phpMyAdmin 中运行它即可查看结果。
  • @Born2DoubleUp 我已经切换到整数输出以方便检查。
【解决方案2】:

这样的事情应该可以工作。 使用名为 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

【讨论】:

  • 请注意,此查询有可能从articles 多次返回同一行。例如,如果 tagstitle 上的行“匹配”。
  • @spencer7593 true 那么主题发起者应该在所有 UNIONS 之后删除关键字 ALL 以删除重复项
  • 使用UNION 代替UNION ALL 并不能真正解决这个问题,因为search_column 返回的值将在查询之间有所不同,'title''tags'。唯一的排序操作将保留两行。
【解决方案3】:

另一种方法是在 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 列表中的表达式。条件测试(LIKE 比较)被评估为 TRUE、FALSE 或 NULL。 MySQL IF 函数会将第一个参数评估为布尔值,如果为真,它将返回第二个参数,否则返回第三个参数。

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

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

 SELECT CASE WHEN a.`title`       LIKE CONCAT('%', ? ,'%') 
             THEN 1
             ELSE 0
        END AS match_in_title

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-03
    • 2022-07-28
    相关资源
    最近更新 更多