I am stuck with a query builder in laravel 8
DB::table('users')
->join('contracts', 'users.id', '=', 'contracts.user_id')
->join('roles', 'roles.id', '=', 'users.role_id')
->select('users.id', 'users.username', 'users.email', DB::raw('COUNT(contracts.user_id) as numberOfContracts'))
->groupBy('users.id')
->paginate(10);
i am getting only 80 of total entries .... and I have 103 users.
I want to display all the users with paginate of course..... and show for each user the role and how many contracts have.
What I did wrong ?
*** UPDATE ***
the tables are these:
users (id, username, email, role_id)
contracts (id, name, user_id)
roles (id, name)
*** update 2 ***
If run the eloquent
User::with('contracts', 'role')
->withCount('contracts')
->paginate(10);
it return all the 103 with count. But how to do it with query builder ?
You were using straight JOIN (which equated to an INNER JOIN since that's what MySQL defaults to) in Laravel Query Builder. It will not account for Empty contracts, or roles. You need a LEFT JOIN to do this.
DB::table('users')
->leftJoin('contracts', 'users.id', '=', 'contracts.user_id')
->leftJoin('roles', 'roles.id', '=', 'users.role_id')
->select('users.id', 'users.username', 'users.email', DB::raw('COUNT(contracts.user_id) as numberOfContracts'))
->groupBy('users.id')
->paginate(10);
See This SO Question to see the difference in JOINS -- Difference in MySQL JOIN vs LEFT JOIN
Related
I'm getting users and counting their likes and their items on other tables. The problem is every time likes_count equals created_count. If I removed the second join of the items. It just works fine and get's the right count for the likes. Any help please. I'm using laravel.
$users = User::select(DB::raw('users.id, users.name,
users.email,users.image,
COUNT(likes.id) AS likes_count,
COUNT(items.id) AS created_count'))
->leftJoin('likes', 'users.id', '=', 'likes.user_id')
->leftJoin('items', 'users.id', '=', 'items.user_id')
->get();
When using Laravel, They discourage to write raw database queries. So Always try to stick with laravel.
$users = User::select(['id', 'name', 'email', 'image'])
->withCount('likes')
->withCount('items')
->get();
It's that simple.
NOTE
Note that you need to have defined those models and relationships.
I just solved the issue. By adding distinct inside count. Thanks to # CHARITRASHRESTHA. I found that answer in the link he provided.
$users = User::select(DB::raw('users.id, users.name,
users.email,users.image,
COUNT(distinct likes.id) AS likes_count,
COUNT(distinct items.id) AS created_count'))
->leftJoin('likes', 'users.id', '=', 'likes.user_id')
->leftJoin('items', 'users.id', '=', 'items.user_id')
->get();
Please add below code into user model.
public function likes(){
return $this->hasMany('App\Model\Likes','user_id','id');
}
public function items(){
return $this->hasMany('App\Model\Items','user_id','id');
}
and use below query to get count:
$users = User::select(['id', 'name', 'email', 'image'])->withCount('likes','items')->get();
I am new in Laravel and facing an issue with the DB query builder.
I want to fetch all the records from users table and want to count related wishlists in wishlists table. Here is my query.
select `users`.*, count(wishlists.id) as wishlists_count from `users` left join `wishlists` on `users`.`id` = `wishlists`.`uid` where `users`.`status` = 1 group by `wishlists`.`id`
I want to do it with laravel query builder. Here is what I am trying.
$leads = DB::table('users')
->selectRaw('users.*', 'count(wishlists.id) as wishlists_count')
->leftJoin('wishlists', 'users.id', '=', 'wishlists.uid')
->where('users.status',1)
->groupBy('wishlists.id')
->get();
It is showing this error.
Argument 2 passed to Illuminate\Database\Query\Builder::selectRaw()
must be of the type array, string given.
Any help will be greatly appreciated.
Thanks in Advance.
This should work. From the documentation, the second argument to selectRaw() is an optional array of bindings.
However, you can achieve what you are looking for with a combination of select() and DB::raw()
$leads = DB::table('users')
->select('users.*', DB::raw('count(wishlists.id) as wishlists_count'))
->leftJoin('wishlists', 'users.id', '=', 'wishlists.uid')
->where('users.status',1)
->groupBy('wishlists.uid')
->get();
Edit: The above answer is wrong. I would consider the following alternatives instead.
Either you could achieve it with a Sub-Query with something like the following:
$wishlist = Wishlist::select(DB::raw('count(wishlists.id)'))
->whereColumn('uid', 'users.id')
->getQuery();
$users = User::select('users.*')
->selectSub($wishlist, 'wishlists_count')
->get();
Or with a much easier way (assuming you have a wishlists relationship set up)
Users::withCount('wishlists')->get();
foreach($users as $user) {
echo $user->wishlists_count;
}
I have a question about Laravel queries, so I have a upload Model and database table which stores all my images. Then there is an Activity Model and database table which stores all my activities. For each activity I want a image.
So my Activity model has a 'uploads_id' column. I wrote the query like this:
$activity_images = DB::table('uploads')
->join('activities', 'uploads.id', '=', 'activities.upload_id')
->where('uploads.id', '=', 'activities.upload_id')
->get();
It cannot find the right image what am I doing wrong?
You are "joining" twice in your join and where clause. You connect uploads.id and activities.upload_id one time in the join and again in the where clause.
If you want to query for a special upload.id, your query should look like this:
$activity_images = DB::table('uploads')
->join('activities', 'uploads.id', '=', 'activities.upload_id')
->where('uploads.id', '=', '<yourUploadID>')
->get();
If you want all images, you can delete the where statement.
$activity_images = DB::table('uploads')
->join('activities', 'uploads.id', '=', 'activities.upload_id')
->get();
If you use join an inner join will be used.
You could also use leftJoin if you want all entries from the table uploads.
$activity_images = DB::table('uploads')
->leftJoin('activities', 'uploads.id', '=', 'activities.upload_id')
->get();
Does it solve your issue?
I am performing a query in which desirable output is first apply where clause then after I want to perform right join.I have this query but it perform first join then where.thank you for you any help advance.
Here is my query
$friends = friend_list::where('friend_lists.user_id', '=', $id)
->rightJoin('users as u1', 'u1.id', '=', 'friend_lists.user_id2')
->where('friend_lists.user_id2','!=',$id)
->where('u1.id','!=',$id)
->orwhere('status',null)
->get();
edited:
I am implementing friend request section.
In which user table contains...user(id,name,..,..) friend_list(userid,userid2,status)
in friend_list shows status with other friend.I do right join withfriend_list.if status is null then there is no row for that user with current user.so status is null and it shows add friend
.so null value is important therefor right join with user table
Change the WHERE to another JOIN condition
$friends = friend_list::rightJoin('users as u1', function($join) {
$join->on('u1.id', '=', 'friend_lists.user_id2')
->where('friend_lists.user_id', '=', $id);
})
->where('friend_lists.user_id2','!=',$id)
->where('u1.id','!=',$id)
->orwhere('status',null)
->get();
Here is my query using fluent query builder.
$query = DB::table('category_issue')
->select('issues.*')
->where('category_id', '=', 1)
->join('issues', 'category_issue.issue_id', '=', 'issues.id')
->left_join('issue_subscriptions', 'issues.id', '=', 'issue_subscriptions.issue_id')
->group_by('issues.id')
->order_by(DB::raw('COUNT(issue_subscriptions.issue_id)'), 'desc')
->get();
As you can see, I am ordering by a count from the joined table. This is working fine. However, I want this count returned with my selections.
Here is the my raw sequel query that works fine.
Select issues.*, COUNT(issue_subscriptions.issue_id) AS followers
FROM category_issue JOIN Issues ON category_issue.issue_id = issues.id
LEFT JOIN issue_subscriptions ON issues.id = issue_subscriptions.issue_id
WHERE category_issue.category_id = 1
GROUP BY issues.id
ORDER BY followers DESC
How would I go about this select using Laravel's fluent query builder? I am aware I can use a raw sql query but I would like to avoid that if possible.
You can use an array in the select() to define more columns and you can use the DB::raw() there with aliasing it to followers. Should look like this:
$query = DB::table('category_issue')
->select(array('issues.*', DB::raw('COUNT(issue_subscriptions.issue_id) as followers')))
->where('category_id', '=', 1)
->join('issues', 'category_issue.issue_id', '=', 'issues.id')
->left_join('issue_subscriptions', 'issues.id', '=', 'issue_subscriptions.issue_id')
->group_by('issues.id')
->order_by('followers', 'desc')
->get();
$count = DB::table('category_issue')->count();
will give you the number of items.
For more detailed information check Fluent Query Builder section in beautiful Laravel Documentation.