codeigniter join count another table - php

$query=$this->db->select('*')
->from('activation')
->join('products','products.id_pro = activation.id_pro')
->join('user','user.id = products.user_p')
->order_by('id_key','DESC')
->get();
return $query->result();
I have these code where I join result from 3 tables abd that works good. What I need more is counted rows from 4.table. That table is called license, and I need to count how many rows are with id_key (primary key for table activation). How to add that in my code?

Try selecting license column as count
$query=$this->db->select('*, COUNT(license.id_key ) as license_count')
->from('activation')
->join('products','products.id_pro = activation.id_pro')
->join('user','user.id = products.user_p')
->join('license','license.id_key = table.column?')
->order_by('id_key','DESC')
->get();
access the count within the object like: $query->result()->license_count;

$query=$this->db->select('BaseTbl.*', 'Products.*', 'User.*', COUNT(License.id_key) as license_count)
->from('activation as BaseTbl')
->join('products as Products','Products.id_pro = BaseTbl.id_pro')
->join('user as User','User.id = Products.user_p')
->join('license as License','License.id_key = BaseTbl.id_key')
->order_by('BaseTbl.id_key','DESC')
->group_by('BaseTbl.id_key')
->get();

Related

Laravel OrderBy by related table column

I have a table (A) that has a One to Many relation with another table (B).
I want to query Table A and eager load Table B with the Table A results - but I also want to sort Table A by a value in Table B.
I have tried using OrderBy in the query and also trying SortBy on the resultant collection but cannot get the Table A data to be sorted by the value found in Table B.
Example of what I have tried:
$query = ModelA::with("ModelB"])->get()->sortByDesc('ModelB.sortValue');
Keep in mind, I am only interested in the LATEST record from Table B. So I need to query Table A and sort by a value in the LATEST records of Table B.
How can I achieve this?
EDIT:
The below (as suggested by #ljubadr) works pretty close, but the issue is that there are many record in Table B which means that it doesn't reliably sort as it doesn't seem to sortby the latest records in Table B. Can I have the join return ONLY the latest record for each ID?
$query = ModelA::select('TableA.*')
->join('TableB', 'TableA.id', '=', 'TableB.col_id')
->groupBy('TableA.id')->orderBy('TableB.sortCol', 'desc')
->with(['x'])
->get();
EDIT 2:
#Neku80 answer has gotten me closest but it seems to not sort the column with the greatest accuracy.. I'm sorting a Decimal column and for the most part it is in order but in some places the items are out of order..
$latestTableB = ModelB::select(['TableA_id', 'sortByColumnName'], DB::raw('MAX(created_at) as created_at'))
->groupBy('TableA_id');
$query = ModelA::select('TableA.*')
->joinSub($latestTableB, 'latest_TableB', function ($join) {
$join->on('TableA.id', '=', 'latest_TableB.TableA_id');
})
->orderBy('latest_TableB.sortByColumnName')
->get();
For example, the ordering is like:
0.0437
0.0389
0.0247 <-- -1
0.025 <-- +1
0.0127
When I delete all rows except for the 'latest' rows, then it orders correctly, so it still must be ordering with old data...
I have found a solution:
ModelA::select('TableA.*', 'TableB.sortByCol as sortByCol')
->leftJoin('TableB', function ($query) {
$query->on('TableB.TableA_id', '=', 'TableA.id')
->whereRaw('TableB.id IN (select MAX(a2.id) from TableB as a2 join TableA as u2 on u2.id = a2.TableA_id group by u2.id)');
})
->orderBy('TableB.sortByCol')
->get();
Another alternative to order is like this:
$users = User::orderBy(
Company::select('name')
->whereColumn('companies.user_id', 'users.id'),
'asc'
)->get();
Here we are ordering in asc order by company name field.
In this article it is explained in detail.
You can simply execute a left join query:
ModelA::query()->leftJoin('model_b_table', 'model_a_table.primary_key', '=', 'model_b_table.foreign_key')->orderBy('model_a_table.target_column')->get();
This should work if you only need TableB's ID and created_at columns:
$latestTableB = ModelB::select('TableA_id', DB::raw('MAX(created_at) as created_at'))
->groupBy('TableA_id');
$query = ModelA::select('TableA.*')
->joinSub($latestTableB, 'latest_TableB', function ($join) {
$join->on('TableA.id', '=', 'latest_TableB.TableA_id');
})
->orderBy('latest_TableB.created_at')
->get();

Laravel return latest histories from all users

I have login history table where i save each user login/logout, therefore each user can have many rows.
I am trying to make filter to get last row of each user at once (getting latest row of all users) but not sure how to.
Code
controller
$histories = LoginHistory::with(['user','user.roles' => function($q) {
return $q->latest()->first();
}])->get();
this return all rows from all users instead of only latest rows.
screenshot
table
In this case my function should return 3 results as my user with id 1 has 2 rows (i only need to get latest one row 2 ) but yet i get all 4 rows with my function.
Any idea?
The raw MySQL query you might use here would look something like this:
SELECT lh1.*
FROM login_history lh1
INNER JOIN
(
SELECT user_id, MAX(login) AS max_login
FROM login_history
GROUP BY user_id
) lh2
ON lh1.user_id = lh2.user_id AND lh1.login = lh2.max_login
Your updated Laravel/Eloquent code:
$subquery = DB::table('login_history')
->select(DB::raw("user_id, MAX(login) AS max_login"))
->groupBy('user_id');
$rs = LoginHistory::joinSub($subquery, 'lh2', function($join) {
$join->on('login_history.user_id', '=', 'lh2.user_id');
$join->on('login_history.login', '=', 'lh2.max_login');
})
->select(['login_history.*'])
->get();

Left join to get a single row in Laravel

I have been unsuccessfully trying to leftjoin and get the required data
Here is my code:
$album = Albums::->where('users_id',$user_id)
->leftJoin('photos',function($query){
$query->on('photos.albums_id','=','albums.id');
$query->where('photos.status','=',1);
//$query->limit(1);
//$query->min('photos.created_at');
})
->where('albums.status',1)->get();
The comments are some of my several trying...
I want to get only a single record from the photos table matching the foreign key album_id which was updated first and also with status 1
pls help...
I have used DB::raw() in order to achieve this
$album = Albums::select( 'albums.*',
DB::raw('(select photo from photos where albums_id = albums.id and status = 1 order by id asc limit 1) as photo') )
->where('users_id',$user_id)
->where('albums.status',1)->get();
#JarekTkaczyk 's coding was similar and displayed the same result as I needed, so a special thanks to him for his time and effort...
But comparing the execution time for the quires I stayed to mine as my above snippet
select `albums`.*, (select photo from photos where albums_id = albums.id and status = 1 order by id asc limit 1) as photo from `albums` where `users_id` = '1' and `albums`.`status` = '1'
took 520μs - 580μs
and #JarekTkaczyk 's
select `albums`.*, `p`.`photo` from `albums` left join `photos` as `p` on `p`.`albums_id` = `albums`.`id` and `p`.`created_at` = (select min(created_at) from photos where albums_id = p.albums_id) and `p`.`status` = '1' where `users_id` = '1' and `albums`.`status` = '1' group by `albums`.`id`
took 640μs - 750μs But both did the same...
You can achieve it using either leftJoin or rightJoin (but the latter would return Photo models, so probably you won't need that):
Albums::where('users_id', $user_id)
->leftJoin('photos as p', function ($q) {
$q->on('photos.albums_id', '=', 'albums.id')
->on('photos.updated_at', '=',
DB::raw('(select min(updated_at) from photos where albums_id = p.albums_id)'))
->where('photos.status', '=', 1);
})
->where('albums.status', 1)
->groupBy('albums.id')
->select('albums.*', fields from photos table that you need )
->get();
Are you trying to check for albums that have the status of '1'? If this is the case you are missing an equals sign from your final where.
Try:
->where('albums.status','=',1)->first();
Alternatively you may be able to achieve this with an 'on' instead of a 'where' inside the join function. You also don't need to split up query inside of the function and can do it as one line with the '->' :
$album = Albums::->where('users_id',$user_id)
->leftJoin('photos',function($query){
$query->on('photos.albums_id','=','albums.id')
->on('photos.status','=',1);
})
->where('albums.status','=',1)->first();
You need to make sure that you are using 'first', as it will return a single row of the first result. Get() will return an array.
As a straightforward answer which results in a single object I suggest the following query:
$album = DB::table('albums')->select('albums.*', 'photos.photo')
->join('photos', 'photos.id', '=', 'albums.id')
->where('users_id',$user_id)
->where('albums.status',1)
->first();

Query for getting values from multiple tables

I have a table video with fields videoid, genre(int-foreign key), language(int-foreign key) etc. I want to get the value of genre from genre table and language from movie_languages table.
The structure of tables are given below:
video
genre
movie_languages
How can I join these 3 tables to get the language and genre related to each videos in video table. Also when user didn't select genre/language in the form, value 0 will be inserted to the table. Will this affect the query. I am using codeingiter and I tried with the following query and is not working.
$this->db->select('video.*,movie_languages.language,genre.genre');
$this->db->join('genre', 'video.genre = genre.id');
$this->db->join('movie_languages', 'video.language = movie_languages.id');
$query = $this->db->get();
Please help me.
Thanks in advance.
It will be, you need a left join in this case
Try this
$query = $this->db
->select('v.*,ml.language,g.genre')
->from('video as v')
->join('movie_languages AS ml', 'v.language = ml.id', 'left outer')
->join('genre AS g', 'v.genre = g.id', 'left outer')
->get();
try this
$this->db->select('video.*,movie_languages.language,genre.genre')
->from('video')
->join('genre', 'video.genre = genre.id')
->join('movie_languages', 'video.language = movie_languages.id');
$query = $this->db->get();

Codeigniter Active Record / MySQL Join Query - How to Return Results if one of the Table Rows is Not Present

I have the following query:
$this->db
->select('SQL_CALC_FOUND_ROWS null as rows
,table1.*
,table2.*
,table3.*', FALSE)
->from('table1')
->where('table1.column1', $user_id)
->join('table2', 'table2.column2 = table1.column2')
->join('table3', 'table3.column2 = table1.column2')
->group_by('table1.column2')
->order_by('table1.column2', 'DESC');
$query = $this->db->get();
The problem is, there may not be a row in table 3 and if there is not, I would still like to return a result with the remainder of the query data. Please could someone advise how to achieve this?
you should do a left join on table3
Use left join and also use group_by to get exact records:
$this->db->join('login_ranknames AS t4', 't4.id = t1.rank', 'left');
$this->db->group_by('t4.id');

Categories