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();
Related
I'm working on a basic messaging functionnality in Laravel and want to display each user who sent a message to the current logged in user along with the last received message, the problem is that the "orderByDesc" isn't working as it displays the first message instead of the last one.
Here's the query I wrote:
$receivedmessages = DB::table('messages')
->join('users', 'users.id', '=', 'messages.sender_id')
->select('messages.*', 'users.username')
->where('receiver_id', Auth::user()->id)
->orderByDesc('messages.created_at')
->groupBy('receiver_id')
->get();
Any idea how I can fix that?
Thanks
Remove ->where('receiver_id', Auth::user()->id) this condition to get a result of each user, instead of the one you're loggedin with
The trick to achieving the above is to get a max Id from a table and use those Ids in WHERE IN condition
$receivedmessages = DB::table('messages')
->join('users', 'users.id', '=', 'messages.sender_id')
->select('messages.*', 'users.username')
->whereRaw('messages.id IN (SELECT MAX(messages.id) FROM messages GROUP BY receiver_id, sender_id)')
->where('receiver_id', Auth::user()->id)
->orderByDesc('messages.created_at')
->get();
I have a problem with getting data. I'm trying to get all users with there max value (points). My question is just like OData filter by max value and field.
Code for my question is:
$query = User::select('users.id','users.username','games.points',
'games.created_at')
->join('games', 'users.id', '=', 'games.user_id')
->whereBetween('games.created_at', [$start, $end]);
But the problem is when I want to remove duplicates and get max points for each user.
In the version where I don't need whereBetween I'm doing in this way:
return User::select('users.id', 'users.username', 'games.points',
'games.created_at')
->join('games', 'users.id', '=', 'games.user_id')
->whereRaw('(users.id, games.points) IN (SELECT user_id, MAX(points)
FROM games GROUP BY user_id)')
->orderByDesc('points')
->get();
Thanks
Why don't you simply GROUP BY your query on users.id and users.username?
-- I let you translate the query into your framework
SELECT users.id, users.username, max(games.points) as points
FROM users, games
WHERE users.id = games.user_id
AND games.created_at BETWEEN $start AND $end
GROUP BY users.id, users.username
ORDER BY max(games.points) DESC
That way, you'll get the max of points per user (id and username).
Hope this helps.
I have resolved my problem with using unique method form eloquent.
Game::with('user')
->whereBetween('created_at', [$start, $end])
->orderByDesc('points')
->orderBy('created_at')
->limit($limit)
->get()
->unique('user_id')
->values();
Thanks a lot to Lucas for his time and his help.
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 to run a query to find out the total orders for each quantity as
SELECT userorders.`delivered` as delivered_status, items.`name` as itemname,
sizes.`size` as sizename,SUM(userorders.`order_qty`) as order_quantity,
sizes.`qty` as stockremaining FROM userorders inner join sizes on
userorders.`size`=sizes.`id` inner join items on sizes.`item_id`=items.`id`
WHERE 1 group by userorders.`delivered`, userorders.`size`;
Roughly, its laravel equivalent is
$userorders = DB::table('userorders')
->join('sizes', 'userorders.size', '=', 'sizes.id')
->join('items', 'sizes.item_id', '=', 'items.id')
->join('categories', 'items.category_id', '=', 'categories.id')
->select('SUM(userorders.order_qty) as order_quantity','userorders.delivered as delivered_status', 'items.name as itemname','categories.name as categoryname', 'sizes.size as sizename','sizes.qty as stockremaining')
->groupBy('userorders.delivered', 'userorders.size')
->get();
But, it seems laravel doesnt support aggregate parameters.
I found out that for getting just the aggregate quantity we could use it as
$userorders = DB::table('userorders')
->join('sizes', 'userorders.size', '=', 'sizes.id')
->join('items', 'sizes.item_id', '=', 'items.id')
->join('categories', 'items.category_id', '=', 'categories.id')
->SUM('userorders.order_qty');
But it seems not to be working in my case for getting the sum as well as other parameters too.
Could someone suggest me the way how to make it work??
Use DB::raw:
$userorders = DB::table('userorders')
->select('userorders.delivered', 'userorders.size',
DB::raw('SUM(userorders.order_qty) as total_qty'))
->join('sizes', 'userorders.size', '=', 'sizes.id')
->join('items', 'sizes.item_id', '=', 'items.id')
->join('categories', 'items.category_id', '=', 'categories.id')
->groupBy('userorders.delivered', 'userorders.size');
Note carefully that I only select three things, the two columns which appear in the GROUP BY clause and the aggregate of the order quantity. Selecting any other non aggregate columns would technically be an invalid query (though MySQL might tolerate it).
To use aggregates with eloquent or the query builder you need to use raw methods. Roughly something like:
->selectRaw('SUM(userorders.order_qty) as order_quantity','userorders.delivered as delivered_status', 'items.name as itemname','categories.name as categoryname', 'sizes.size as sizename','sizes.qty as stockremaining')
See the docs: https://laravel.com/docs/5.5/queries#raw-expressions
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.