Laravel: query with a different where condition in a different row - laravel

I have a classrooms table with a "quota" column that has different values. In one class, there are many students. How to display classrooms data with where condition which total students per row < "quota" ? Here's the table : .
Code :
Classroom::with('subject.teacher')->with('students')->whereHas('subject', fn ($query) => $query->where('grade', $grade))->withCount('students')->having('students_count', '<', 'quota');
when I use this code the result is empty
when "having" is removed this is the result :
The desired result only displays 3 classroom

You can use the has and a DB::raw.
// Simplified version
Classroom::has('students', '<=', DB::raw('classrooms.quota'))->get();

The withCount function appends an additional select column to your query. It does not use GROUP BY which is typically what is used in conjunction with having.
You can't actually filter by subqueries that are added in the select. However fortunately Laravel allows you to select rows based on how many related models they have using has. This query is also added as a subquery, but within the where clauses so you can also use column names within it like below:
Classroom::with('subject.teacher')
->with('students')
->whereHas('subject', fn ($query) => $query->where('grade', $grade))
->has('students', '<', \DB::raw('quota'))
->withCount('students');

Related

Laravel query use parent column inside whereRelation

I have problem with my eloquent query, i need to use data of my base model into whereRelation.
I tried this query bottom, but results was not what i except. The query return me all users who have one city relation, not only user who have city updated between my last user sync.
$users = People::whereRaw('TIMESTAMPDIFF(SECOND, people.latest_sync, people.updated_at) > 20')
->orWhereRelation('city', 'updated_at', '>', 'people.updated_at')
->get();
I'v tried people.updated_at and latest_sync in value of my Where Relation
Do i need to make pure SQL Raw query with classic join ?
PS: the first whereRaw is ok, and work (i really need)

I want to extract the first five data that match the where clause from Laravel relationships

I'd like to do something like this with Laravel's Eloquent:relationship, but it doesn't work.
$playlist->setRelation('tags', $playlist->tags->where('privacySetting', 'public')->take(5));
It works without where clause, but I want to retrieve the first 5 data in the tags relationship table that match the where clause.
How can I do this?
Laravel version is 7.28.1.
this will select top 5 based on criteria from model
$playlist = Playlist::with(['tags' => function($filter){
return $filter->where('privacySetting', 'public')
->take(5);
}])
->get();
//try dd($playlist);

Laravel eloquent with relation data (Eager Loading)

I have two database tables items and measurement_units - item has measurement unit.
Now the problem is I want to select a particular column from items and some column from measurement_unit. I want to use Eager loading
e.g.
$items_with_mu = Item::with("measurement_unit")->select(["item_name", "item_stock"])->first();
When accessing measurement_unit. It returns null. Without the select function it returns data(measurement_unit).
$items_with_mu->measurement_unit;
can anyone help me and sorry for my English.
Try this
Item::with(['measurement_unit' => function($q) {
$q->select('id','unit_column'); //specified measurement_unit column
}])
->select('id','measurement_unit_id','item_name')
->get();
If your laravel version is >=5.5 then you can write in a single line
Item::with('measurement_unit:id,unit_column')
->select('id','measurement_unit_id','item_name')
->get()
You have to select the primary column of the main model like below.
items_with_mu = Item::with("measurement_unit")->select(["item_name", "item_stock", "primary_key"])->first();

Search query from joined table in Laravel 5.3

I have a books table that contains many subject on my subjects table (one-to-many relationship).
I tried to join my tables like this:
$book = Book::latest()
->leftjoin('subjects', 'books.id', '=', 'subjects.book_id')
->select('books.*', 'subjects.subject')
->where('subject', 'like', '%' .$search. '%')
->paginate(20);
I want a search query that will display the books having subjects matched form the $search variable. However, it keeps displaying a book redundantly depending on how many subjects of a book that matched on the $search variable since a book has many subjects.
I only want to display a book once, regardless of how many subjects the book matched.
This image below was the output of the search query I made, the value of the $search= ""
On the second image notice that I search "a" on the search box:
The book entitled "Special Education assessment: Issues strategies affecting today's classrooms" (see it on the first image; it was being redundant 6 times since the subjects of that book was 6)
To display a book only once you have to group by book id (or any other unique column)
->groupBy('books.id');
Mind you, as mentioned in the MySQL doc here
SQL92 and earlier does not permit queries for which the select list, HAVING condition, or ORDER BY list refer to nonaggregated columns that are not named in the GROUP BY clause.
Hence the error message 'bisu_ccc_library.books.ISBN' isn't in GROUP BY
To bypass this, turn off strict in Laravel and everything will work nicely.
Go to config/database.php and in the mysql configuration array, change strict => true to strict => false
I think you want to use distinct for your select
$book = Book::latest()
->leftjoin('subjects', 'books.id', '=', 'subjects.book_id')
->select('books.*', 'subjects.subject')
->distinct()
->where('subject', 'like', '%' .$search. '%')
->paginate(20);
Just like in regular SQL (which it will translate to) it will "Force the query to only return distinct results." (from laravel api docs)
The SELECT DISTINCT statement is used to return only distinct
(different) values.
Inside a table, a column often contains many duplicate values; and
sometimes you only want to list the different (distinct) values.
The SELECT DISTINCT statement is used to return only distinct
(different) values. - W3Schools

Provide extra condition in eager loading which includes comparing of two columns, laravel

I have tables students, profiles, subjects and pivot table profile_subject
-students---------{id,profile_id,year}
-profiles---------{id}
-profile_subject--{profile_id,subject_id,year}
-subjects---------{id}
I want to select a student with id 5, and eager load profile and subjects for the students year.
Something like this:
$student = Student::with('profile','profile.subjects')->find(5);
But I also have to insert the condition
->wherePivot('year','=','students.year')
there somewhere. How to do that?
This query will not do the job cos it will search for records which year is "students.year" literary
Use lazy eager loading. This code will not create any additional queries, it'll create the same amount of queries as with() would:
$student = Student::find(5);
$sudent->load(['profile', 'profile.subjects' => function ($q) use ($student) {
$q->wherePivot('year', $student->year);
}]);

Resources