【问题标题】:How to prioritize result in laravel eloquent如何在 laravel eloquent 中对结果进行优先级排序
【发布时间】:2018-02-10 01:40:57
【问题描述】:

我有一张有 4 列的表格。我想根据输入显示该行,它应该能够根据优先级字段优先显示。

示例:我的表格如下所示:

ID  title          description    tags
1   web developer  designer       front-end
2   designer       front-end      web developer
3   front-end      web developer  designer

下面有我的测试用例应该如何工作:

$input = 'web developer' // the sequence should be IDs : 1, 3, 2
$input = 'front-end'     // output sequence result is : 3, 2, 1
$input = 'designer'      // result sequence : 2, 1, 3

现在,我想根据输入对从标题到标签的结果进行优先级排序。

$blog = DB::('blogs')
        ->where('title', 'LIKE', '%$title%')
        ->where('description', 'LIKE', '%$title%')
        ->where('tags', 'LIKE', '%$title%');

但是上面的代码,好像没有..

【问题讨论】:

    标签: php sql laravel eloquent


    【解决方案1】:

    我认为您想要排序结果的逻辑应该出现在ORDER BY 子句中。考虑以下原始查询:

    SELECT *
    FROM yourTable
    ORDER BY
        CASE WHEN title = 'web developer'       THEN 0 ELSE 1 END,
        CASE WHEN description = 'web developer' THEN 0 ELSE 1 END,
        CASE WHEN tags = 'web developer'        THEN 0 ELSE 1 END;
    

    输出:

    这是我尝试使用 orderByRaw 时 Laravel 代码的样子:

    $orderByClause  = "CASE WHEN title = '".$input."' THEN 0 ELSE 1 END,";
    $orderByClause .= "CASE WHEN description = '".$input."' THEN 0 ELSE 1 END,";
    $orderByClause .= "CASE WHEN tags = '".$input."' THEN 0 ELSE 1 END";
    
    $blog = DB::('blogs')
            ->orderByRaw($orderByClause)
            ->get();
    

    我找不到关于如何参数化 orderByRaw 的任何(工作)文档,所以我改用字符串连接。

    演示在这里:

    Rextester

    【讨论】:

      【解决方案2】:

      不是一个好的解决方案,但这可能会对您有所帮助,

      $input = 'web developer';
      
      $byTitle = DB::('blogs')
                 ->where('title', 'LIKE', '%$input%')
                 ->select('id');
      
      $byDescription = DB::('blogs')
                       ->where('description', 'LIKE', '%$input%')
                       ->select('id');
      
      $byTag = DB::('blogs')
               ->where('tag', 'LIKE', '%$input%')
               ->select('id');
      
      $ids = $byTitle->union($byDescription)->union($byTag)->get();
      

      您可以根据列选择id,然后将它们联合起来获取数据。

      如果您想通过UNION 处理此问题,原始查询将如下所示:

      SELECT ID, 1 AS priority
      FROM blogs
      WHERE title = 'web developer'
      UNION
      SELECT ID, 2
      FROM blogs
      WHERE description = 'web developer'
      UNION
      SELECT ID, 3
      FROM blogs
      WHERE tags = 'web developer'
      ORDER BY
          priority,
          ID
      

      这里需要注意的是,如果给定记录的两个或多个标题、描述或标签列的值相同,那么您最终会在结果集中出现重复记录。从您的原始数据来看,这似乎没有发生,尽管这是一个值得一提的极端情况。

      【讨论】:

      • 你有逻辑人,但我认为如果你有数百万数据,这将太慢
      • 我认为您还需要一个 ORDER BY 子句来完成这项工作。您可以在 UNION 查询中添加一个计算列来跟踪每个子查询,然后在最后按该列排序。
      • @samuel 是的,这就是为什么我提到“不是一个好的解决方案”
      • @TimBiegeleisen 我认为三个不同的查询将一个一个地执行,因此将计算出所需的结果。感谢您的建议
      • @SagarGautam 我用您可能必须在 MySQL 中使用的实际原始查询更新了您的答案。我认为您需要引入一个计算列来跟踪每个批次的位置。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多