php - SQL 查询将逗号分隔的字符串与逗号分隔的字符串进行匹配?

标签 php mysql

下面的 MySQL 查询使用 PHP 提取 $sector(单个数字)和 $subsector_text(逗号分隔的字符串)。 $subsector_text 可以是单个数字或多个 ID 的列表,例如“3,4,7,9”。

  $sql = "
SELECT DISTINCT a.id
              , a.name
              , a.category_id
              , a.sector
              , a.subsector
              , a.year_in_operation
              , a.state
              , a.total_value
              , b.country_id
              , b.project_id
              , c.isocode_3
              , c.name
           FROM com_barchan_project a
           JOIN com_barchan_location b
             ON b.project_id = a.id
           JOIN com_barchan_country c
             ON c.id = b.country_id
           JOIN com_barchan_project_value_join d
             ON a.id = d.project_id
          WHERE a.state = 1 
            AND a.sector = '$sector'
            AND a.subsector REGEXP '^{$subsector_text}[,]|[,]{$subsector_text}[,]|[,]{$subsector_text}$|^{$subsector_text}$'
          ORDER 
             BY a.total_value DESC
              , a.category_id ASC
              , a.name ASC
";

我在上面的查询中遇到的问题是以下行:

AND a.subsector REGEXP '^{$subsector_text}[,]|[,]{$subsector_text}[,]|[,]{$subsector_text}$|^{$subsector_text}$'  

如果 $subsector_text = "3,4,5,9",则仅返回 $subsector 字段中恰好包含“3,4,5,9”的记录。

期望的结果是它将返回具有 $subsector_text 中任何值的任何记录。例如,所有这些都应该返回,但目前还没有。此列表只是一个示例,并不准确。

1,3
1,5
1,3,7,9
3,5
3,4,5,9
9
3
5
4

如何更改查询以选择具有 $subsector_text 字符串中的值的任何记录?

请注意:如果 $subsector_text = 11,则不应选择以下内容。

1
12
21

任何帮助将不胜感激。

最佳答案

在单个谓词中将逗号分隔字符串中的任何值与另一个逗号分隔字符串中的任何值进行匹配是不切实际的。

您可以使用FIND_IN_SET()一次搜索一个值。

这意味着您需要多个谓词,一个谓词对应通过拆分输入 $subsector_text 获得的每个值。因此,拆分变量并将其映射到一系列 FIND_IN_SET() 调用中。

我尚未测试以下代码,但它应该能让您了解我在说什么:

$subsector_array = array_map('intval', explode(',', $subsector_text));
$subsector_terms = array_map(
  function ($id) { return "FIND_IN_SET($id, a.subsector)"; },
  $subsector_array);
$subsector_expr = implode(' OR ', $subsector_terms);

$sql = "
SELECT ...
          WHERE a.state = 1 
            AND a.sector = '$sector'
            AND ($subsector_expr)
...";

这当然会强制进行表扫描,因为无法索引 FIND_IN_SET() 或任何其他搜索子字符串的操作。好吧,我想您对 a.statea.sector 的条件将在应用 FIND_IN_SET() 条件之前使用索引来缩小搜索范围。

我理解必须使用您继承的系统所面临的困境。让您的经理知道这需要在某个时候进行重构,因为它永远不会像现在的设计方式那样高效或可靠。

关于php - SQL 查询将逗号分隔的字符串与逗号分隔的字符串进行匹配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44008546/

相关文章:

java - 我无法在 NetBeans 中查看或编辑 MySQL 存储过程

php - 在数据库表的不同列上上传不同的文件

mysql - SQL更新具有重复信息的数据

php - 如何创建其他连接 zf2 apigility?

php - 如何缓存动态 iPhone Web 应用程序以便离线工作?

javascript - 当用户代理来自 webview android 应用程序时,如何隐藏网站标题(div)?

php - 如何使用 php 和 mysql 将行中的单词分开

php - 更新mysql查询损坏

mysql - SQL 使用 INNER JOIN 更新选定的行

mysql - 如何使用 Resque 在父子之间共享 MySQL 连接?