Count of group by in CodeIgniter - codeigniter

I wan to display the first 9 places which have the highest number of reservations. So I must have a count of $this->db->group_by('t.id_pl') and then an order by of that counted number.
I've managed to do this but I don't understand where should I put the count :
function select_pop ()
{
$this->db->select( 's.place as place, s.price as price, s.title as title' );
$this->db->from('Places AS s');
$this->db->join('Reservations AS t', 't.id_pl= s.place', 'INNER');
$this->db->group_by('t.id_pl');
$this->db->order_by('');
$this->db->limit(9);
$result = $this->db->get();
return $result;
}
Any suggestions?

you can add count in your select statement like below-
$this->db->select('count(t.id_pl) as reservation_count,s.place as place, s.price as price, s.title as title');
Then for order by you can use like-
$this->db->order_by('reservation_count','DESC');
i hope this will help you..

Related

Laravel Query Builder and Eloquent query builder add an odd phrase when I try to build the query on the fly?

I am attempting to build a query on the fly depending upon what is entered in a form. When I do so, I check what the sql statement is in the Console. I have OR and AND contitions, so I use a call back to build the query. the SQL statement that results is:
select `id`, `activity_name`, `activity_name_web`, `year`, `season`, `sex`,
`active_on_web`, `begin_active_on_web`, `end_active_on_web`, `begin_age`,
`end_age`, `begin_date`, `end_date` from `activities` where (season='fall'
OR season='summer' is null) order by `begin_date` desc, `activity_name` asc
limit 25 offset 0 []
notice the words "is null". I can't determine how this phrase is being added.
The Code:
$qry_where = "1";
$arry_Season = array();
if($this->a_fall)
$arry_Season[] = "LOWER(`season`)='fall'";
if($this->a_spring)
$arry_Season[] = "LOWER(`season`)='spring'";
if($this->a_summer)
$arry_Season[] = "LOWER(`season`)='summer'";
if($this->a_winter)
$arry_Season[] = "LOWER(`season`)='winter'";
if(count($arry_Season)>0) {
$qry_where = $arry_Season[0];
if(count($arry_Season)>1){
array_shift($arry_Season);
foreach($arry_Season as $season){
$qry_where .= " OR " . $season;
}
}
}
$activities = Activity::select('id','activity_name','activity_name_web','year','season', 'sex', 'active_on_web',
'begin_active_on_web', 'end_active_on_web', 'begin_age', 'end_age', 'begin_date','end_date')
->where(function($query) use ($qry_where) {
if($qry_where == "1")
$query->where('id','>',0);
else {
$query->where(DB::raw($qry_where));
}
})
->orderBy('begin_date','desc')->orderBy('activity_name','asc')
->paginate(25);
So, if the users checks the box labelled "fall", I add it to the query builder.
so - Where is the phrase "is null" coming from.
select `id`, `activity_name`, `activity_name_web`, `year`, `season`, `sex`,
`active_on_web`,`begin_active_on_web`, `end_active_on_web`, `begin_age`,
`end_age`, `begin_date`, `end_date` from `activities`
where (season='fall' OR season='summer' is null)
order by `begin_date` desc, `activity_name` asc limit 25 offset 0 []
btw, say I check fall and summer, then I ddd($qry_where) just before I build the query, I get this:
"LOWER(`season`)='fall' OR LOWER(`season`)='summer'"
I also need to mention that I am using a livewire component.
thanks for the help in advance.
#apokryfos thank you for your quick answer. It was driving me crazy. It seems when I passed a variable into the ->where(DB::raw()), it evaluated the variable too late for the ->when() to see that the variable contained a comparison?
In any case, I tweeked the solution that #apokryfos a bit and came up with the following:
$activities = Activity::select('id','activity_name','activity_name_web','year','season', 'sex', 'active_on_web',
'begin_active_on_web', 'end_active_on_web', 'begin_age', 'end_age', 'begin_date','end_date',
'cost_member','cost_non_member')
->when(count($seasons) > 0, function($query) use ($seasons) {
$query->whereIn('season', $seasons);
})
->orderBy('begin_date','desc')->orderBy('activity_name','asc')
->paginate($this->items_on_page);
the ->whereIn() could not process the "DB::raw('LOWER(season)', $seasons)" as suggested. If i want to make sure that the data in the [activities].[season] column, I will either have to make sure the seasons are input into the table in lower case, or do a ->select(DB:raw('LOWER(season)') in the SQL statement. I like the first option.
thank you again for your input apokryfos
You did a where(<raw query>) which defaults to do a WHERE <raw query> is not NULL since WHERE assumes a comparison. Here's what I think is a more concise version of your query:
$seasons = array_filter([
$this->a_spring ? 'spring' : null,
$this->a_summer ? 'summer' : null,
$this->a_fall ? 'fall' : null
$this->a_winter ? 'winter' : null
]);
$activities = Activity::select('id','activity_name','activity_name_web','year','season', 'sex', 'active_on_web',
'begin_active_on_web', 'end_active_on_web', 'begin_age', 'end_age', 'begin_date','end_date')
->when(count($seasons) > 0, function($query) use ($seasons) {
$query->whereIn(DB::raw('LOWER(season)'), $seasons);
})->when(count($seasons) == 0, function ($query) {
$query->where('id', > 0); // Not sure you need this part
})
->orderBy('begin_date','desc')->orderBy('activity_name','asc')
->paginate(25);

Laravel return restaurants with their rate average

<?php
$query = $this->restaurant->leftJoin('reviews', 'reviews.restaurant_id', '=', 'restaurants.id');
$query = $user_id == null ? $query : $query->where("user_id", $user_id);
$query = $query->select('restaurants.*')
->selectRaw('ROUND(AVG(reviews.rating), 1) as average_rating')
->groupBy('restaurants.id')
->havingRaw('AVG(reviews.rating) >= ?', [$request->from_rating])
->havingRaw('AVG(reviews.rating) <= ?', [$request->to_rating])
->orderByDesc("average_rating")
->paginate(
$this->perPage,
['id', 'name', 'image', 'description', 'filesystem', 'created_at'],
'page',
$request->page
);
return $query;
My query looks like this. I have two tables: Restaurants and Reviews. The Reviews table stores restaurant_id. The problem occurs when we have, for example, 10 restaurants and we have 1 Review only for one of the Restaurants. After running this query, only 1 restaurant is returned, because I use havingRaw which filters Restaurants according to the average rating. So if a Restaurant doesn't have any rating, that Restaurant doesn't get returned.
How do I make that so all Restaurants still return, but their average rating becomes 0?
you can use CASE WHEN to populate mysql with more specific condition. Also you may change the datatype of 'rating' table to int(5), in this case all the empty value will be shown as 0. So that will go as you want according to your question.

Sorting a field based on several values in Laravel

I have an array of city codes
$cities=[9,12,14,2,3,4,5,6,8,10,11,13]
My posts table has a foreign key named city_id
I want sorting posts based on the values of this array
In this way: the first posts of the city 9 then the posts of the city 12 and then posts of city 14 and etc to be loaded
I tried using this method but this is wrong
$posts->orderByRaw('city_id in ? desc',$cities);
Can you help me find the best solution?
The only way i can i think of doing something like that(at least right now) is by doing something like so
$all_posts = [];
$cities=[9,12,14,2,3,4,5,6,8,10,11,13];
foreach ($cities as city) {
$city_posts = Post::whereRaw('city_id = ?', $city)->orderByRaw('created_at DESC');
array_push($all_posts, $city_posts);
}
dd($all_posts);
1st find all the posts relevant to cities and then sort w.r.t given order like
$cities = [9,12,14,2,3,4,5,6,8,10,11,13]; // order you'd like to see with posts
$posts = Post::whereIn('city_id', $cities)->sort(function($a, $b) uses ($cities) {
$pos_a = array_search($a->getAttributes()['city_id'], $cities);
$pos_b = array_search($b->getAttributes()['city_id'], $cities);
return $pos_a - $pos_b;
})->get();
// $posts contains the required order with city_ids
You can use raw query with "CASE something THEN index" this way you tell the query to see something as index so you can assign 0 to the first item in your array.
$sql .= "....";
foreach($cities as $index => $city) {
$sql .= "CASE {$city} THEN {$index}";
}
$sql .= "....";
Thanks to the friends solution,I used this method, and I think it's less complicated than the suggested methods of friends
$posts=$posts->orderByRaw('FIELD(city_id, '.$cities->implode( ', ').') asc')->orderBy('created_at','desc')->get();

Query max Codeigniter

I have a query that result 2 data(s) with the same employee
$this->load->library('datatables');
$this->datatables->select('a.employee_id, a.name, b.employee_position');
->from('employee a')
->join('employee_position b','b.employee_id = .a.employee_id AND `b`.`deleted`=0 AND `c`.`date_start` <= "'.$now_date.'"','inner')
$data = $this->datatables->get_adata();
$aaData = $data->aaData;
I wan't only one data appear which is choosing the max data on date_start column, how to do it?
Add these two lines in your code:
$this->db->order_by('c.date_start', 'DESC');
$this->db->limit(1, 1);

How to select all column from multiple tables in codeigniter using join?

I have 4 tables like this:
Now, I want to select all columns from all tables where model.featured=1. i.e.
model.id
model.name
model_attributes.id
model_attributes.attributes_value
model_images.id
model_images.model_images
attributes.id
attributes.name
attributes.value
I can only do basic level queries and I'm not sure if I'm anywhere near to the solution but this is what I have tried (returns nothing):
$this->db->select('*');
$this->db->from('model');
$this->db->join('model_images','model.id = model_images.model_id','RIGHT');
$this->db->join('model_attributes','model.id = model_attributes.model_id','RIGHT');
$this->db->join('attributes','model_attributes.attributes_id = attributes.id','RIGHT');
$this->db->where('model.featured', 1);
$query = $this->db->get();
return $query->result();
How do I achieve what I want ? Or, is there any other better methods to do it ?
// try this query
$this->db->select('*');
$this->db->from('model');
$this->db->join('model_images','model_images.model_id = model.id');
$this->db->join('model_attributes','model_attributes.model_id = model.id');
$this->db->join('attributes','attributes.id = model_attributes.attributes_id');
$this->db->where('model.featured','1');
$query = $this->db->get()->result();
return $query;
Please go through below mentioned solution.
$this->db->select('model.*,model_images.*,model_attributtes.*, attributes.*'):
Let me know if it not works for you.
Please go through below solution. If multiple table has same column name then you have to give alias for each column name which have same name in both the table. because by default CI merge all column name and generate result.
$this->db->select('*,c.name as c_name,s.name as s_name');
$this->db->from('country c');
$this->db->join('state s', 'c.id = s.country_id');
$query = $this->db->get();

Resources