Average of a calculated second average in Laravel Query Builder - php

I have 3 tables : Appointments, Reviews, Review_ratings
Each review_ratings has a rating value. Each review has many review_ratings and finally, eeach appointment has many reviews.
What I am trying to do is to calculated the average of review_ratings per review, and then calculate the average of reviews total ratings and see if it is higher than a specific int.
Exemple:
Apointment id : 1, has 2 Reviews, each review has review_rating one of 4 and 3 and review rating number 2 of 5 and 5.
AVG(review_ratings) should return the average between average(5,5) and average(4,3) which is 3.5 then AVG(the_first_avg) should return average (3.5,5) which is 4.25.
My last tested query is :
if($minRating > 0){
$search->join('appointments','appointments.doctor_id','users.id')
->join('reviews','reviews.appointment_id','appointments.id')
->join('review_ratings','review_ratings.review_id','reviews.id')
->addSelect(array('review_ratings.id',
DB::raw('AVG(review_ratings.rating) as review_ratings_count')
))
->addSelect(
DB::raw('AVG(review_ratings_count) as ratings_avg')
)
->where('ratings_avg','>=',$minRating)
;
}
The error I'm getting is
Column not found: 1054 Unknown column 'review_ratings_count' in 'field
list'

I found the solution to be much simpler that my code, and using AVG(name_of_column) rather than using the 'AS' value
->selectRaw('AVG(review_ratings.rating) as overall_rating')
->when($minRating > 0, function ($query) use($minRating)
{
$query->havingRaw('AVG(review_ratings.rating) >= ?', [$minRating]);
})

Related

How to use case with withSum in laravel?

I have a posts table and a comments table. A post can have many comments. comments has a field called stars. I want to get all posts alongside the rank. Rank is basically the stars in comments where if the stars is 3 then the rank would be 5.
I tried the following,
Route::get('/', function () {
return Post::withSum(
'comments as rank'
, 'CASE WHEN stars > 3 THEN 5 ELSE 0 END')->get();
});
I get the error,
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'comments.CASE WHEN stars > 3 THEN 5 ELSE 0 END' in 'field list'
SELECT
`posts`.*,
(
SELECT
sum(
`comments`.`CASE WHEN stars > 3 THEN 5 ELSE 0 END`
)
FROM
`comments`
WHERE
`posts`.`id` = `comments`.`post_id`
) AS `rank`
FROM
`posts`
Looks like laravel is messig up the syntax comments.CASE WHEN stars > 3 THEN 5 ELSE 0 END. How do I fix it?
Repository: https://github.com/axelthat/laravel9-issue

Count products that are bought together

I have made a query that counts how many products are bought together, but I don't want to have the products both ways in it
Code
DB::table(DB::raw('tenant_db.sales_data as b'))
->selectRaw('a.product_id as product_id, b.product_id as bought_with, count(*) as times_bought_together')
->join(DB::raw('tenant_db.sales_data as a'), function ($join){
$join->on('a.sale_id', '=', 'b.sale_id');
$join->on('a.product_id', '!=', 'b.product_id');
})
->groupBy('a.product_id', 'b.product_id');
Output
Product_id Bought_with times_bought_together'
52 24 3
24 52 3
So I only want to have it one time not twice, is that possible (based on quantity)?
Use < rather than !=:
$join->on('a.product_id', '<', 'b.product_id');

How do i query percentages in a select tag

I am trying to get the percentages of the industry_id compared to the adtype_id. So the example below for industry id 2, It should be 1/3 and 2/3 for a total of 100%. I get the records 1 and 2 but how do i get the total count of industry id using this select query is what i am having trouble with. This part of the code is not correct select count(*) from ads This is giving output of all the records of the column i just want total record specific to the id of the industry id .
adtype_id industry_id
2 2
3 2
3 2
result i want: 1/3, 2/3
$intantype = Ad::
join('industries', 'industries.id', 'ads.industry_id')
->join('adtypes', 'adtypes.id', 'ads.adtype_id')
->where('ads.industry_id', $id)
->Select('ads.adtype_id',DB::raw('count(*) *100 / (select count(*) from ads) as total '), 'industryname')
->groupBy('adtype_id','industryname')
->get();

Laravel Eloquent 3 queries into one

What I'm trying to achieve is doing 3 queries in one go, to limit the n1+ problem :
given we have 3 models :
trips
id => int
price => float
city_id => uint
........
cities
id => int
name => varchar
........
ratings:
id => int
ratable_id => int
rate => small-int
......
pseudocode:
select from tours where price >= 100
-then from the result
select from cities where id in result.city_id as cities
select count from ratings where ratable_id in result.id as rates groupBy rate
so the result is
[
trips => list of the trips where price more than or equal 100
cities=> list of the cities those trips belongs to
rates => list of rating with it's count so like [1 => 5, 2 => 100] assuming that '1 and 2' are the actual rating , and '5,100' is the trips count
]
how would I achieve that?
Two ways to go, Use eloquent methods which is preferred approach or use joins a single query to get your desired results
Moving forward with eloquent way i assume you have defined your models and their mappings based on their type of relationship (1:m, m:m)
$trips= Trips::with('city')
->withCount('ratings')
->where('price', '>=', 100)
->get();
Moving forward with join
$trips = DB::table('trips as t')
->select('t.id', 't.price','c.name',DB::raw('count(*) as rating_count'))
->join('cities as c' ,'t.city_id', '=' , 'c.id')
->join('ratings as r' ,'t.ratable_id', '=' , 'r.id')
->where('t.price', '>=', 100)
->groupBy('t.id', 't.price','c.name')
->get();
Trip Model Relationship
public function city(){
return $this->belongsTo(City::class);
}
public function ratings(){
return $this->hasMany(Rating::class, 'ratable_id'); //assuming ratable_id is an id of trips table
}
Fetch Data
$trips= Trip::with('city', 'ratings')
->where('price', '>=', 100)
->get();
Print Data
foreach($trips as $trip){
$trip->city->name." - ". $trip->price." - ". $trip->ratings()->avg('rate');
}

Group values and get percentage from database

I have a database table where I save players bets it the following logic:
This table will of course have several user_id's for every match_id. I want to display how the users have placed their bets. If they think that the home team will win lose or draw. AND I want it to be stated in percentage.
Germany - France 35% - 20% - 45%.
So far I have managed to calculate the quantity guesses, but not the percentage, with the following query:
SELECT games.home_team,games.away_team,COUNT(*) as 'qty',user_result_bet.match_id,(
CASE
WHEN `home_score` > `away_score` THEN 'home'
WHEN `home_score` < `away_score` THEN 'away'
ELSE 'draw'
END) as 'tipped_result'
FROM user_result_bet,GAMES
WHERE games.match_id = user_result_bet.match_id
GROUP BY tipped_result, match_id
ORDER BY match_id
Where do I go from here? I want to turn this in to percentage somehow? Im using PHP for the website
you need to use count if
SELECT user_result_bet.match_id,COUNT(*) as 'qty',
count(if(`home_score` > `away_score`,1,null))/count(*)*100 as home_percent,
count(if(`home_score` < `away_score`,1,null))/count(*)*100 as away_percent,
count(if(`home_score` = `away_score`,1,null))/count(*)*100 as draw_percent
from wherever
group by 1
SUM(CASE WHEN `home_score` > `away_score` THEN 1 ELSE 0 END)/COUNT(*) AS PercentageHome

Categories