简体   繁体   中英

Return the average for each record in table

I have a table that returns categories for products. Their is another table (called inventory_review) that has reviews that customers have left for the products. How can I in the foreach loop of the actual category, also loop through each review to find the average rating for that particular product.

I can easily do it on the product page itself and just use AVG on the statement, but on the categories it's only showing the first review.

Mysql

     $category = Inventory::select('inventory_review.rating','inventory_images.image', 'inventory.id' , 'inventory.sku', 'inventory.name', 'inventory.price', 'inventory_categories.category')
        ->join('inventory_categories', 'inventory.sku', '=', 'inventory_categories.sku')
        ->leftJoin('inventory_images', 'inventory.sku', '=', 'inventory_images.sku')
        ->leftJoin('inventory_review', 'inventory.id', '=', 'inventory_review.inventory_id')
        ->where('inventory_categories.category', 'LIKE', '%'.$cat.'%')
        ->where('inventory.active', '=', 1)
        ->where('inventory.stock_quantity', '>', 2)
        ->groupby('inventory.id')
        ->paginate(16);

So basically what happens is it will loop through all the products that matches the category and only return the 1st review rating for the product. I know I probably need to loop through something but not sure what.

@if($inventory->rating > 0)
    @for ($i=1; $i <= 5 ; $i++)
        @if($i <= $inventory->rating)
            <i class="fa fa-star"></i>
        @else
            <i class="fa fa-star-o"></i>
        @endif
    @endfor
@endif

You should use the AVG() function here as well. (Don't know the class you're using, but I would guess something like this)

$category = Inventory::select('AVG(inventory_review.rating) AS averageRating','inventory_images.image', 'inventory.id' , 'inventory.sku', 'inventory.name', 'inventory.price', 'inventory_categories.category')
        ->join('inventory_categories', 'inventory.sku', '=', 'inventory_categories.sku')
        ->leftJoin('inventory_images', 'inventory.sku', '=', 'inventory_images.sku')
        ->leftJoin('inventory_review', 'inventory.id', '=', 'inventory_review.inventory_id')
        ->where('inventory_categories.category', 'LIKE', '%'.$cat.'%')
        ->where('inventory.active', '=', 1)
        ->where('inventory.stock_quantity', '>', 2)
        ->groupby('inventory.id')
        ->paginate(16);

Since you're using GROUP BY at the end, only the first reviews rating will be returned if you don't specify what it should do with the rating of each review (AVG(), MAX(), MIN(), SUM() or what it may be you wish to accomplish).

Accepted Niklas answer but had to edit it to fit within Laravel docs

        $category = Inventory::select(DB::raw('AVG(inventory_review.rating) AS averageRating'),'inventory_images.image', 'inventory.id' , 'inventory.sku', 'inventory.name', 'inventory.price', 'inventory_categories.category')
            ->join('inventory_categories', 'inventory.sku', '=', 'inventory_categories.sku')
            ->leftJoin('inventory_images', 'inventory.sku', '=', 'inventory_images.sku')
            ->leftJoin('inventory_review', 'inventory.id', '=', 'inventory_review.inventory_id')
            ->where('inventory_categories.category', 'LIKE', '%'.$cat.'%')
            ->where('inventory.active', '=', 1)
            ->where('inventory.stock_quantity', '>', 2)
            ->groupby('inventory.id')
            ->paginate(16);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM