Select from junction table - doctrine

everybody!
What should I do if I need to make select from junction table?
For example, I develop project and I need to make chats between users. I have two entities: User and Chat, and many-to-many relation between them (accordingly, I have three tables: user, chat, chat_user). I try to get all chats, which user is member, and to get all users from these chats.
I made the following SQL query:
SELECT *
FROM chat c
INNER JOIN chat_user cu ON c.id = cu.chat_id
INNER JOIN user u ON u.id = cu.user_id
WHERE c.id IN (SELECT chat_id
FROM chat_user
WHERE user_id = <idUser>);
But I don't know how to translate in DQL subquery SELECT chat_id FROM chat_user WHERE user_id = <idUser>, because a haven't additional entity for table chat_user.
And I tried to add entity ChatUser and get data in ChatRepository smt. like this:
public function getChatsData($idUser)
{
$subQuery = $this->getEntityManager()
->getRepository(ChatUser::class)
->createQueryBuilder('chus')
->select('chus.chat')
->andWhere('chus.user = :idUser')
->setParameter('idUser', $idUser)
;
$qb = $this->createQueryBuilder('c');
return $qb
->innerJoin('c.chatUsers', 'cu')
->addSelect('cu')
->innerJoin('cu.user', 'u')
->addSelect('u')
->innerJoin('c.messages', 'm')
->addSelect('m')
->andWhere('u.id = :idUser')
->andWhere($qb->expr()->in(
'c.id',
$subQuery->getDQL()
))
->setParameter('idUser', $idUser)
->getQuery()
->getResult()
;
}
but it doesn't work. I get error [Semantical Error] line 0, col 12 near 'chat FROM App\Entity\ChatUser': Error: Invalid PathExpression. Must be a StateFieldPathExpression.
Have Doctrine standard tools for such tasks?

Related

How to sort with COUNT laravel eloquent relations between 3 tables

I have the following function that lists the Leads and the pages, I am asked to sort it by the activities but I have the problem that this is from another table if I do it in SQL mode I get the result, but with the actual writing of the code I don't get it.
This is my query, it has join with contacts and a left join with activities, the problem is that I only need to be able to sort it by activities.
SELECT l.id,l.status_id,l.user_id,l.created_at,l.ticket_id,l.last_lead, c.full_name, COUNT(a.lead_id) as total FROM `leads` l join contacts c on l.contact_id = c.id left join activities a on a.lead_id =l.id where active=1 and status_id=7 and project_id in (8,9,10,11) GROUP by l.id order by total desc;
And this is my eloquent query:
Order by comments.
if ($sortField == 'last_comment') {
$user = User::withRole(['salesman'])->pluck('id');
$sortField = Comment::select('created_at')
->whereColumn('comments.lead_id','leads.id')
->where('comments.user_id',implode(',',$user->toArray()))
->latest()
->take(1);
}
$leads_ = $this->leads
->openedStage() // where status_id = 7
->ticketActive() // where active = 1
->searchTickets($projects)
->orderBy($sortField,'desc')
->paginate((int)$per_page);
Where the following methods mean:
**openedStage()**: where status_id = 7
**ticketActive()**: where active = 1
**searchTickets($projects):
whereHas('contacts', function ($q) use ($projects){
$q->whereIn('project_id',$projects->toArray());
});

Which is the best efficient way to get many-to-many relation count in laravel?

I have students and subjects table in many-to-many relation (pivot table is student_subject).
Student Model
public function subjects()
{
return $this->belongsToMany(Subject::class, 'student_subject');
}
Subject Model
public function students()
{
return $this->belongsToMany(Student::class, 'student_subject');
}
Here I want the particular student subjects counts. I tried the below methods it's working fine but I want the best efficient way for this purpose.
1.
$student = Student::find($id);
$subject_count = $student->subjects()->count();
I checked the SQL query through laravel debuger it shows as below
select * from `students` where `students`.`id` = '10' limit 1
select count(*) as aggregate from `subjects` inner join `student_subject` on `subjects`.`id` = `student_subject`.`subject_id` where `student_subject`.`student_id` = 10 and `subjects`.`deleted_at` is null
$student = Student::withCount('subjects')->find($id);
$subject_count = $student->subjects_count;
I checked the SQL query through laravel debuger it shows as below
select `students`.*, (select count(*) from `subjects` inner join `student_subject` on `subjects`.`id` = `student_subject`.`subject_id` where `students`.`id` = `student_subject`.`student_id` and `subjects`.`deleted_at` is null) as `subjects_count` from `students` where `students`.`id` = '10' limit 1
$student = Student::find($id);
$subject_count = $student->loadCount('subjects')->subjects_count;
I checked the SQL query through laravel debuger it shows as below
select * from `students` where `students`.`id` = '10' limit 1
select `id`, (select count(*) from `subjects` inner join `student_subject` on `subjects`.`id` = `student_subject`.`subject_id` where `students`.`id` = `student_subject`.`student_id` and `subjects`.`deleted_at` is null) as `subjects_count` from `students` where `students`.`id` in (10)
$student = Student::find($id);
$subject_count = DB::table('student_subject')->where('student_id', $student->id)->count();
I checked the SQL query through laravel debuger it shows as below
select * from `students` where `students`.`id` = '10' limit 1
select count(*) as aggregate from `student_subject` where `student_id` = 10
According to the above ways which one is best and why? or if any different best way also there?
Doing relation()->count() is probably faster.
But if all you need is the count, withCount() should be better in terms of memory consumption.

how to write a Oracle view with this query?

I am using oracle 11g. I want to query with 3 queries.
First one, it is the main. Select to find condition.
Select role, name from tablerole where name is not null and ID=#param1;
This query will return #role with 2 level (admin and user)
The 2 other sub queries will base on this condition.
Up on the first query.
If role='admin' then select*from tablescreen where name is not null and ID=#param1;
If role='user' then select*from tablescreen where name='2';
#param1 is given when I call this view or when I using.
I consider it will be view or function or procedure best for this query.
How to write this query that can accept an input parameter into the query for looping source and return output where matched condition.
Thanks for your kindness.
Nam hmoob.
As far as I understood the question, that would be a view that consists of two select statements:
one that uses condition for admin
another one for user
The first query you posted will be used in a join with the tablescreen table. Something like this:
create or replace view v_role as
-- select for ADMIN
select r.id, s.whatever
from tablescreen s join tablerole r on r.id = s.id
where s.name is not null
and r.role = 'admin'
union all
-- select for USER
select r.id, s.whatever
from tablescreen s join tablerole r on r.id = s.id
where s.name = '2'
and r.name = 'user';
Or, as Zynon suggested, without union:
select r.id, s.whatever
from tablescreen s join tablerole r on r.id = s.id
where ( s.name is not null
and r.role = 'admin'
)
or ( s.name = '2'
and r.name = 'user'
);
You'd then use it as
select * from v_role v where v.id = &param1;

Laravel 5.4 Eloquent multiple table query

Hi I want to form a query in laravel 5.4 eloquent for the following SQL:
select A.*, concat(B.firstname, ' ', B.lastname) as clientname, C.category as category from payments A, clients B, categories C where A.client_id = B.id and A.category_id = C.id
All the foreign keys are properly given and the models are also properly created.
My aim is to get all the master record name like category, client name, etc to come in the child table record set directly.
You can try this:
DB::table('payments')
->select('payments.*',DB::raw('CONCAT(clients.firstname," ",clients.lastname) as clientname'),categories.category)
->join('clients','clients.id','=','payments.client_id')
->join('categories','categories.id','=','payments.category_id')
->get();
Hope this help for you !!!
Paste your row query in DB::row() and print data like following
$data= DB::row("select A.*, concat(B.firstname, ' ', B.lastname) as clientname, C.category as category from payments A, clients B, categories C where A.client_id = B.id and A.category_id = C.id")->get();
dd($data);
if your query is right and properly managed relation than its retrieve data
If you already made Models than Why you don't use ORM?
Use Models,
payment::leftJoin('clients ','payments.client_id','=','clients.id')
->leftJoin('categories ','payments.category_id ','=','categories .id')->select(['payment.*','categories.category',DB::raw("CONCAT(clients.firstname,' ',clients.lastname) as clientname")])->get();

Entity Framework Query select hard-coded user created column

I'm creating a select from multiple tables using a union as I need to return a list of activities that has occurred for a particular client on the database. I need to return each union with an added column so I can tell the difference between the results. If I was to do the query in SQL it would look something like this:
SELECT cn.NoteID, cn.Note, cn.InsertedDate, 'Note Added' Notes
FROM Client c
INNER JOIN ClientNotes cn ON cn.ClientID = c.ID
WHERE c.ClientID = #ClientID
UNION
SELECT rc.ID, rc.CommNote, rc.InsertedDate, 'Communication Added' Notes
FROM ReceivedCommunication rc
LEFT JOIN Job j ON j.ID = rc.JobID
WHERE j.ClientID = #ClientID or rc.ClientID = #ClientID
My Question is how in Entity Framework using IQuerable do I return the hard-coded Notes column?
I have something like this so far:
Dim client as IQueryable(Of myresultclass) =
(From c As Client
Join cn As ClientNotes In ClientCompanyNotes On c.ID Equals cn.ClientID
Where c.ClientID = ClientID
Select cn.NoteID, cn.Note, cn.InsertedDate).Union(
From rc As ReceivedCommunication In ReceivedCommunications
Join j As Job In Jobs On j.ID Equals rc.JobID
Where j.ClientID = ClientID or rc.ClientID = ClientID
Select rc.ID, rc.CommNote, rc.InsertedDate)
Thanks for your help
Ok worked it out, should have been obvious. For anyone with the same issue, I had to update my Select from Select cn.NoteID, cn.Note, cn.InsertedDate to:
Select New myresultclass With {
.ActivityID = cn.NoteID,
.ActivityType = "Note Added"
.InsertedDate = cn.InsertedDate
}
for each one of the unions that I had
Thanks

Resources