Laravel 5.5 select users based on session with roles as - mysql

I want to select all users of sessions where roles for the users are not admin or only roles where roles.name is user.
my user table is
session table is
and roles table is this
I am running this query and it is working fine but it selects all users including admin user. I only want to select user where roles.name is user
$sessions = Sessions::where('user_id', '<>', 'NULL')
->join('users', 'users.id', 'sessions.user_id')
->select('users.first_name','users.last_name',
DB::raw('count(sessions.user_id) as counts'))
->get();

You have first to join the roles with the users table, since there is no way with the set up you gave to know what is the role of a certain user, so after adding role_id as a foreign key in the users table you can make your query like this:
$sessions = Sessions::where('user_id', '<>', 'NULL')
->join('users', 'users.id', 'sessions.user_id')
->join('roles', 'roles.id', 'users.role_id')
->where('roles.name','user')
->select('roles.name as role','users.first_name','users.last_name',
DB::raw('count(sessions.user_id) as counts'))
->get();

You can use DB query for this..
DB::table(sessions)->where('roles', $user->hasRole('user'))->get();
:)

Related

laravel query builder count relationship

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

groupBy is expecting more table columns in many to many relationship

I'm trying to get all the roles permission which has a many to many relationship. I want to get all the permissions of a single role. Here I'm trying to use groupBy but it gives me error.
$search_role = DB::table('roles')
->join('roles_permissions','roles_permissions.role_id','roles.id')
->join('permissions','permissions.id','roles_permissions.permission_id')
->where('roles.name', 'like', "%$request->searcher%")
->orWhere('permissions.name', 'like', "%$request->searcher%")
->select('roles.name as role_name', 'permissions.name as permission_name','roles_permissions.*')
->groupBy('roles_permissions.role_id')
->get();
Error here:
roles_permissions.permission_id isn't in groupBy.
If I add that I get another column isn't in groupBy.
you don't have any aggregation operation in select statement. check my example
$search_role = DB::table('roles')
->join('roles_permissions','roles_permissions.role_id','roles.id')
->join('permissions','permissions.id','roles_permissions.permission_id')
->where('roles.name', 'like', "%$request->searcher%")
->orWhere('permissions.name', 'like', "%$request->searcher%")
->select('role_id', DB::raw('count(*) as total')) //example
->groupBy('roles_permissions.role_id')
->get();
what you are trying to do does not makes sense. Group by does not work in that way.
SELECT role_id, count(*)
from roles
group by role_id
is valid
SELECT roles.*, count(*)
from roles
group by role_id
is not. in the latter case, you generally need to add every column which is not aggregated to group by statement

How to get "unique" users by combining email and date

I am using Laravel 5.5.
I have a database which contains users. The problem is that some users exist more than one time because of a bug. I want to query my database and select all "unique" users.
By using the word "unique" I mean the below :
If a user with email "test#test.com" exists 50 times I want the row that created_at is closest to now.
My query, which returns all users is written below :
DB::table('users')
->select('name', 'surname', 'email', 'phone', 'answers', 'newsletter', 'created_at')
->get();
I got confused and I'm not sure if i should use limit combining it with order by created_at column.
Any ideas?
Ok, this is what you need to do: First off, you get a table with the users in their last created_at 'version'. Now you have a list of emails and dates. Then you perform a left join of all the users with that temporary table.
TL;DR:
$users = DB::select('select t1.* from users t1 right join (SELECT email, MAX(created_at) as created_at from users group by email) as t2 on t1.email=t2.email and t1.created_at=t2.created_at');
I hate raw SQL, and I hate subqueries, but this is the only way I know using generic SQL (I mean, you could do a better MySQL or MSSQL native queries, but this should do for you.)
You can use
DB::table('users')->select('name', 'surname', 'email','phone','answers','newsletter','created_at')->orderBy('created_at', 'desc')->groupBy('email')->get();
For more help refer Order By before Group By using Eloquent (Laravel)
What you need is groupby and orderby
try this code
DB::table('users')->select('name', 'surname', 'email','phone','answers','newsletter','created_at')
->orderBy('created_at', 'desc')
->groupBy('email')
->get();
hope it will help you if you need further info try above link!
To get latest user record among duplicates you can use a self join
DB::table('users as u')
->select('u.*')
->leftJoin('users as u1', function ($join) {
$join->on('u.email', '=', 'u1.email')
->whereRaw(DB::raw('u.created_at < u1.created_at'));
})
->whereNull('u1.id')
->get();
In plain SQL it would be something like
select u.*
from users u
left join users u1 on u.email = u1.email
and u.created_at < u1.created_at
where u1.id is null

How can I get all entities without a specific related entity?

I have these tables:
users
id
name
events
id
name
entries
id
user_id
event_id
How can I get all users that do not have an entry with event_id 4?
With this code:
$users = User::query();
$users->leftJoin('entries', 'users.id', '=', 'entries.user_id')
->where('event_id','!=', $event_id)->get();
I still get users that already have an entry for that specific event.
This is what I want:
Get all entries which have event_id 4
Get the user_id from those entries
Remove other entries which have that user_id.
$entries = Entry::where(event_id, '=', 4)->get();
foreach ($entries as &$entry) {
//remove all entries from $entries array which "user_id = $entry->user_id"
}
How can I do the above with just a query?
Going by your question following is the answer but i guess this is not what you finally want. so elaborate more and specify the sample input and output datasets
select * from your_table where event_id <> 4;
The SQL you want is:
select user_id
from t
group by user_id
having sum(event_id = 4) = 0;
select u.*
from User u
left join entries e
on e.user_id = u.id and e.event_id = 4
where e.id is null
You're looking for <>, not !=. Also you're not letting it know which table event_id is on.
Try
$users = User::query();
$users->leftJoin('entries', 'users.id', '=', 'entries.user_id')
->where('entries.event_id','<>', $event_id)->get();
More information can be found at https://laravel.com/docs/5.4/queries#where-clauses
You can use the whereDoesntHave builder method.
$users = User::query()->whereDoesntHave("entry", function($q) use ($event_id) {
$q->where('id', $event_id);
})->get();
The method takes a closure in which you can define criteria for the related entities that must not exist.
If you need the users and the entries, I think you can still join the entries using with.
$users = User::query()
->with('entries')
->whereDoesntHave("entry", function($q) use ($event_id) {
$q->where('id', $event_id); })
->get();

How can I select with count() on specific user in Laravel?

Here is my Database structure:
Also - there is a table users and reciever_id references that table id.
I use that query to get count of each type of notifications as well as data for that type of notifications from notification_types table.
Notification::
select('notification_types.*', DB::raw('count(*) as total'))
->join('notification_types', 'notifications.type_id', '=', 'notification_types.id')
->groupBy('notifications.type_id')
->get()
What I need - is to set constraint on reciever_id, I just don't get - where should I put the where clause?
Just chain the where method anywhere before get, since your condition will be applied on the notifications table:
Notification::select('notification_types.*', DB::raw('count(*) as total'))
->join('notification_types', 'notifications.type_id', '=', 'notification_types.id')
->where('reciever_id', $receiverId)
->groupBy('type_id')
->get();
Also, there's no need with this query to group by notifications.type_id, type_id will do, because there are no ambiguities created here because there are no other columns named type_id.