laravel查询被称为pior

时间:2017-06-15 23:49:43

标签: php laravel laravel-5

我有以下代码来获取模型的所有评级信息,因为您可以看到有很多查询正在进行评级信息可以更好地完成此功能,特别是对于查询有效负载,所以它&#39 ;每次要求提供此信息时,都不会耗尽服务器。

public function ratingInfo() {

    $totalCount  = $this->ratings()->count();  
    $one_star    = $this->ratings()->where('rating', '>', 0)->where('ratings', '<=', 1);
    $two_star    = $this->ratings()->where('rating', '>', 1)->where('ratings', '<=', 2);
    $three_star  = $this->ratings()->where('rating', '>', 2)->where('ratings', '<=', 3);
    $four_star   = $this->ratings()->where('rating', '>', 3)->where('ratings', '<=', 4);
    $three_star  = $this->ratings()->where('rating', '>', 4)->where('ratings', '<=', 5);

    return [
        'avgRating'   => $this->avgRating(),
        'ratingCount' => $this->ratingCount(),
        'one_star'    => ['count' => $one_star->count(),  'percent' => round(($one_star->count()   * $totalCount) / 100, 2)],
        'two_star'    => ['count' => $two_star->count(),  'percent' => round(($two_star->count()   * $totalCount) / 100, 2)],
        'three_star'  => ['count' => $two_star->count(),  'percent' => round(($three_star->count() * $totalCount) / 100, 2)], 
        'four_star'   => ['count' => $four_star->count(), 'percent' => round(($four_star->count()  * $totalCount) / 100, 2)], 
        'five_star'    => ['count' => $five_star->count(), 'percent' => round(($five_star->count()  * $totalCount) / 100, 2)], 
    ];
}

我是这样想的,如果你只是像这样开始一个查询。

$ratings = $this->ratings->all();
/* then use $ratings again and again how*/
$totalCount = $ratings->count();
$one_star = then query the $ratings collection here but how

评级模型:

class Rating extends Model
{
    protected $table = 'ratings';

    protected $fillable = ['rating', 'comment', 'user_id', 'rateable_id', 'rateable_type'];   

    public function rating()
    {
        return $this->morphTo();
    } 
}

这就是答案:

public function ratingInfo() {

    $result = [];

    $one_star = $this->ratings->filter(function ($item, $key) { 
        return $item->rating > 0 && $item->rating <= 1;
    });

    $two_star = $this->ratings->filter(function ($item, $key) { 
        return $item->rating > 1 && $item->rating <= 2;
    });

    $three_star = $this->ratings->filter(function ($item, $key) { 
        return $item->rating > 2 && $item->rating <= 3;
    });

    $four_star = $this->ratings->filter(function ($item, $key) { 
        return $item->rating > 3 && $item->rating <= 4;
    });

    $five_star = $this->ratings->filter(function ($item, $key) { 
        return $item->rating > 4 && $item->rating <= 5;
    });

    $totalCount = $this->ratings->count();  
    $avgRating = $this->avgRating(2);  
    $totalRatings = $this->ratings->sum('rating');
    //dd('sum: ' . $one_star->sum('rating') . ' count: ' . $one_star->count() . ' percent: ' . round(($one_star->sum('rating') / $this->ratings->sum('rating')) * 100, 2));

    return [
    'total_count' => $totalCount,
    'average_rating' => $avgRating,
    'total_ratings' => $totalRatings,
        'one_star' => [
            'sum' => $one_star->sum('rating'),
            'count' => $one_star->count(),
            'percent' =>  round(($one_star->sum('rating') / $totalRatings) * 100, 2)
        ],
        'two_star' => [
            'sum' => $two_star->sum('rating'),
            'count' => $two_star->count(),
            'percent' =>  round(($two_star->sum('rating') / $totalRatings) * 100, 2)
        ],
        'three_star' => [
            'sum' => $three_star->sum('rating'),
            'count' => $three_star->count(),
            'percent' =>  round(($three_star->sum('rating') / $totalRatings) * 100, 2)
        ],
        'four_star' => [
            'sum' => $four_star->sum('rating'),
            'count' => $four_star->count(),
            'percent' =>  round(($four_star->sum('rating') / $totalRatings) * 100, 2)
        ],
        'five_star' => [
            'sum' => $five_star->sum('rating'),
            'count' => $five_star->count(),
            'percent' =>  round(($five_star->sum('rating') / $totalRatings) * 100, 2)
        ]
    ];
}

3 个答案:

答案 0 :(得分:1)

我会尝试这样的事情:

$this->ratings()->selectRaw('rating, count(*) as C')
     ->groupBy('rating')
     ->orderBy('rating', 'DESC');

这个想法是计算每个等级1到5的计数,每行有各自的计数

$this->whereHas('ratings', function($query) {
      $query->selectRaw('rating, count(*) as C')
            ->groupBy('rating')
            ->orderBy('rating', 'DESC')
})->get();

执行此操作时出错:

$all = $this->ratings()->get();

return $all;

您可以通过执行

进一步简化此操作
$this->ratings->groupBy('rating')->each(function ($group) {
     return count($group);
});

答案 1 :(得分:1)

您可以执行一个查询并使用php过滤结果:

public function ratingInfo() {

    $all = $this->ratings()->get();
    $count = $all->count();
    $one_star = $all->filter(function ($item, $key) {
        return $item->rating === 1;
    });
    $two_star = $all->filter(function ($item, $key) {
        return $item->rating === 2;
    });
    $three_star = $all->filter(function ($item, $key) {
        return $item->rating === 3;
    });
    $four_star = $all->filter(function ($item, $key) {
        return $item->rating === 4;
    });
    $five_star = $all->filter(function ($item, $key) {
        return $item->rating === 5;
    });

    return [
        'avgRating'   => $this->avgRating(),
        'ratingCount' => $this->ratingCount(),
        'one_star'    => ['count' => $one_star->count(),  'percent' => round(($one_star->count()   * $totalCount) / 100, 2)],
        'two_star'    => ['count' => $two_star->count(),  'percent' => round(($two_star->count()   * $totalCount) / 100, 2)],
        'three_star'  => ['count' => $two_star->count(),  'percent' => round(($three_star->count() * $totalCount) / 100, 2)], 
        'four_star'   => ['count' => $four_star->count(), 'percent' => round(($four_star->count()  * $totalCount) / 100, 2)], 
        'five_star'    => ['count' => $five_star->count(), 'percent' => round(($five_star->count()  * $totalCount) / 100, 2)], 
    ];
}

答案 2 :(得分:0)

尝试使用case表达式构建一个旋转函数,将结果作为一个查询执行的一部分,这将大大优化服务器负载,请注意mysql没有原生的旋转功能,这就是为什么我建议你使用case表达式, 那么你必须使用laravel查询构建器方法将查询作为原始查询执行。 以下是仅示例,尝试相应地重写它并运行它..

select id,
sum(case when value = 1 then 1 else 0 end) ANSWER1_COUNT,
sum(case when value = 2 then 1 else 0 end) ANSWER2_COUNT
from survey
group by answer