【问题标题】:SQL, Laravel score/rank results using selectRaw and LIKE?使用 selectRaw 和 LIKE 的 SQL、Laravel 得分/排名结果?
【发布时间】:2020-11-28 18:22:13
【问题描述】:

这适用于单个名称...

Result::whereIn('id', $log->result_ids)
      ->select('*')
      ->selectRaw("(owner LIKE ? ) + 
                   (owner LIKE ? ) + 
                   (city LIKE ? ) AS score", 
                   ['%CHARLOTTE%', '%RICHARD%', 'Salem'])
      ->get();

但我想动态使用一组所有者、城市等...

$owners = [ 
     'CHARLOTTE', 
     'RICHARD'
     // ... or more 
];
$cities = [ 
     'SALEM', 
     'PORTLAND'
     // ... or more 
];

Result::whereIn('id', $log->result_ids)
      ->select('*')
      ->selectRaw("(owner LIKE ? ) + 
                   (city LIKE ? ) AS score", 
                   [$owners, $cities])
      ->get();

@Mehmet Bütün,这是我修改后的答案,它确实有效。有没有更清洁的方法?

$spouses = ['Patricia', 'Cindy'];
$cities  = ['Riverside', 'San Diego'];

$string_to_spouse_score = collect($spouses)->map( function($spouse) {
      return "(owner LIKE '%".strtoupper($spouse)."%' )";
})->join(' + ') . " as spouse_score";

$cities_string = collect($cities)->map( function($city) {
      return strtoupper($city);
})->join(' OR city LIKE ');

Result::whereIn('id', $result_ids)->select('*')
      ->selectRaw("(owner LIKE ? ) as owner_score", ['%'.strtoupper($owner->first_name).'%'])
      ->selectRaw($string_to_spouse_score) // as spouse_score
      ->selectRaw("(city LIKE ? ) as city_score", [$cities_string])
      ->selectRaw("(SELECT(owner_score)) + (SELECT(spouse_score)) + (SELECT(city_score)) as score")
      ->having('score', '>', 0)
      ->orderBy('score', 'desc')
      ->get(); 

【问题讨论】:

    标签: sql laravel ranking


    【解决方案1】:

    您正在尝试使用array 而不是string。试试这个(我希望它会起作用):

    $owners = [ 
         'CHARLOTTE', 
         'RICHARD'
         // ... or more 
    ];
    $cities = [ 
         'SALEM', 
         'PORTLAND'
         // ... or more 
    ];
    
    
    $new_owners=array();
    foreach ($owners as $owner){
        $new_owners[]='%'.$owner.'%';
    }
    $owners_query_string= implode(' OR owner LIKE ', $new_owners);
    
    
    $new_cities=array();
    foreach ($cities as $city){
        $new_cities[]='%'.$city.'%';
    }
    $cities_query_string= implode(' OR city LIKE ', $new_cities);
    
    Result::whereIn('id', $log->result_ids)
          ->select('*')
          ->selectRaw("(owner LIKE ? ) + 
                       (city LIKE ? ) AS score", 
                       [$owners_query_string, $cities_query_string])
          ->get();
    

    【讨论】:

    • 几乎可以工作......它不会获得多场比赛。如果多个所有者匹配,则仅以这种方式计算一个。
    • 你上面写的代码是这样的。你能具体解释一下你想做什么吗?
    • 我正在根据所有者和城市匹配对结果进行评分...如果我知道如何编写它,我就不会问这个问题 ;) 如果有多个所有者匹配,则分数应该反映而不是得分 1。我尝试根据您得分倍数的答案重写解决方案。我想出了一个可行的版本,但它看起来一点也不优雅。我把它贴在上面……你怎么看?
    • @Robert 你有一个复杂的查询。我已经查看了您共享的代码,但我必须说仍有部分我不明白(例如:$obit->first_name)。您可以直接编写 SQL 代码。但我认为“如果它有效,请不要碰它”:)
    猜你喜欢
    • 2021-12-04
    • 1970-01-01
    • 1970-01-01
    • 2012-05-15
    • 1970-01-01
    • 2015-09-02
    • 1970-01-01
    • 2016-03-28
    • 2021-10-24
    相关资源
    最近更新 更多