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

Laravel中如何按匹配OR条件的数量对SQL查询结果排序?

解决方法

原生SQL实现

你可以通过计算每条记录匹配条件的数量来实现排序,WHERE子句的短路逻辑不影响排序时的条件判断——因为排序阶段会单独对每个条件进行评估,不会触发短路。

具体做法是把每个LIKE条件转换成1(匹配)或0(不匹配),求和后得到匹配次数,最后按这个结果降序排列:

SELECT *,
    (
        IF(name LIKE '%test%', 1, 0) +
        IF(title LIKE '%test%', 1, 0) +
        IF(text LIKE '%test%', 1, 0) +
        IF(author LIKE '%test%', 1, 0)
    ) AS match_count
FROM articles
WHERE name LIKE '%test%'
   OR title LIKE '%test%'
   OR text LIKE '%test%'
   OR author LIKE '%test%'
ORDER BY match_count DESC;

如果是PostgreSQL这类不支持IF语法的数据库,换成CASE表达式即可:

SELECT *,
    (
        CASE WHEN name LIKE '%test%' THEN 1 ELSE 0 END +
        CASE WHEN title LIKE '%test%' THEN 1 ELSE 0 END +
        CASE WHEN text LIKE '%test%' THEN 1 ELSE 0 END +
        CASE WHEN author LIKE '%test%' THEN 1 ELSE 0 END
    ) AS match_count
FROM articles
WHERE name LIKE '%test%'
   OR title LIKE '%test%'
   OR text LIKE '%test%'
   OR author LIKE '%test%'
ORDER BY match_count DESC;

Laravel框架实现

用Laravel的Query Builder或Eloquent可以轻松实现这个逻辑,核心同样是构建match_count字段后排序:

方法一:Query Builder 原生写法

$searchTerm = 'test';
$articles = DB::table('articles')
    ->selectRaw("*,
        (
            IF(name LIKE ? , 1, 0) +
            IF(title LIKE ? , 1, 0) +
            IF(text LIKE ? , 1, 0) +
            IF(author LIKE ? , 1, 0)
        ) AS match_count",
        ["%{$searchTerm}%", "%{$searchTerm}%", "%{$searchTerm}%", "%{$searchTerm}%"]
    )
    ->where(function ($query) use ($searchTerm) {
        $query->where('name', 'LIKE', "%{$searchTerm}%")
              ->orWhere('title', 'LIKE', "%{$searchTerm}%")
              ->orWhere('text', 'LIKE', "%{$searchTerm}%")
              ->orWhere('author', 'LIKE', "%{$searchTerm}%");
    })
    ->orderByRaw('match_count DESC')
    ->get();

方法二:Eloquent 模型写法

如果你用Eloquent模型,可使用更优雅的addSelect方式:

use App\Models\Article;

$searchTerm = 'test';
$articles = Article::query()
    ->addSelect([
        'match_count' => function ($query) use ($searchTerm) {
            $query->selectRaw("
                IF(name LIKE ? , 1, 0) +
                IF(title LIKE ? , 1, 0) +
                IF(text LIKE ? , 1, 0) +
                IF(author LIKE ? , 1, 0)
            ", ["%{$searchTerm}%", "%{$searchTerm}%", "%{$searchTerm}%", "%{$searchTerm}%"]);
        }
    ])
    ->where(function ($query) use ($searchTerm) {
        $query->where('name', 'LIKE', "%{$searchTerm}%")
              ->orWhere('title', 'LIKE', "%{$searchTerm}%")
              ->orWhere('text', 'LIKE', "%{$searchTerm}%")
              ->orWhere('author', 'LIKE', "%{$searchTerm}%");
    })
    ->orderBy('match_count', 'desc')
    ->get();

注意:如果项目用PostgreSQL,把代码中的IF替换成CASE WHEN ... THEN 1 ELSE 0 END即可适配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 07:02:15