You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL/Laravel实现反向FIND_IN_SET:匹配字符串包含的分隔值

实现MySQL逗号分隔列的反向匹配(与FIND_IN_SET逻辑相反)

MySQL原生实现

要实现「输入字符串包含列中某一个逗号分隔值」的匹配,核心是先将逗号分隔的列拆分为单个值,再逐一检查是否被输入字符串包含。优先推荐用递归CTE(Common Table Expression)实现,兼容性和准确性更好。

假设你的表名为your_table,存储逗号分隔值的列名为target_column,输入字符串为'The Dog Jumps High',示例SQL如下:

SET @input_str = 'The Dog Jumps High';

WITH RECURSIVE split_values AS (
    -- 初始化:提取每条记录的第一个分隔值
    SELECT 
        id,
        target_column,
        SUBSTRING_INDEX(target_column, ',', 1) AS single_value,
        SUBSTRING(target_column, LENGTH(SUBSTRING_INDEX(target_column, ',', 1)) + 2) AS remaining_values
    FROM your_table
    WHERE target_column IS NOT NULL AND target_column != ''
    
    UNION ALL
    
    -- 递归拆分剩余的分隔值
    SELECT 
        id,
        target_column,
        SUBSTRING_INDEX(remaining_values, ',', 1) AS single_value,
        SUBSTRING(remaining_values, LENGTH(SUBSTRING_INDEX(remaining_values, ',', 1)) + 2) AS remaining_values
    FROM split_values
    WHERE remaining_values IS NOT NULL AND remaining_values != ''
)
-- 筛选存在符合条件的单个值的记录,去重避免重复返回
SELECT DISTINCT t.*
FROM your_table t
JOIN split_values sv ON t.id = sv.id
WHERE LOCATE(sv.single_value, @input_str) > 0;

补充说明

  • LOCATE函数是大小写敏感的,若需忽略大小写,可改为LOCATE(LOWER(sv.single_value), LOWER(@input_str)) > 0;
  • 如果你的MySQL版本低于8.0(不支持CTE),可以用正则匹配的替代方案(仅适合输入无特殊正则字符的场景):
SET @input_str = 'The Dog Jumps High';

SELECT *
FROM your_table
WHERE target_column REGEXP CONCAT('(^|,)', REPLACE(REGEXP_REPLACE(@input_str, '[^a-zA-Z0-9 ]', ''), ' ', '|'), '(,|$)');

Laravel Eloquent实现

方式1:递归CTE方案(推荐,Laravel 8+支持)

通过DB::withExpression定义递归CTE,结合Eloquent查询构造器实现:

use Illuminate\Support\Facades\DB;
use App\Models\YourModel;

$inputStr = 'The Dog Jumps High';

$results = YourModel::query()
    ->withExpression('split_values', function ($query) {
        $query->select('id', 'target_column')
            ->selectRaw("SUBSTRING_INDEX(target_column, ',', 1) AS single_value")
            ->selectRaw("SUBSTRING(target_column, LENGTH(SUBSTRING_INDEX(target_column, ',', 1)) + 2) AS remaining_values")
            ->from('your_table')
            ->whereNotNull('target_column')
            ->where('target_column', '!=', '')
            ->unionAll(function ($query) {
                $query->select('id', 'target_column')
                    ->selectRaw("SUBSTRING_INDEX(remaining_values, ',', 1) AS single_value")
                    ->selectRaw("SUBSTRING(remaining_values, LENGTH(SUBSTRING_INDEX(remaining_values, ',', 1)) + 2) AS remaining_values")
                    ->from('split_values')
                    ->whereNotNull('remaining_values')
                    ->where('remaining_values', '!=', '');
            });
    })
    ->join('split_values', 'your_table.id', '=', 'split_values.id')
    ->whereRaw("LOCATE(split_values.single_value, ?) > 0", [$inputStr])
    ->distinct()
    ->get();

方式2:简化正则匹配(适合简单场景)

如果输入字符串不含特殊正则字符,也可以直接用whereRaw快速实现:

use App\Models\YourModel;

$inputStr = 'The Dog Jumps High';
// 转义正则特殊字符,避免匹配异常
$escapedInput = preg_quote($inputStr, '/');
// 替换空格为|,匹配输入中包含的任意片段
$pattern = "(^|,)" . str_replace(' ', '|', $escapedInput) . "(,|$)";

$results = YourModel::query()
    ->whereRaw("target_column REGEXP ?", [$pattern])
    ->get();

补充说明

  • 若需忽略大小写,可在whereRaw中修改为LOCATE(LOWER(split_values.single_value), LOWER(?)) > 0;
  • 请将代码中的your_table、target_column、YourModel替换为实际业务对应的表名、字段名和模型类。

内容的提问来源于stack exchange,提问作者sony1976

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 02:25:15