Can I use group by query in my codeigniter model?
Some articles says it has been removed.
And I cannot get my result array of group by query.
here is my model
function get_data2(){
$this->db->select('*');
$this->db->from('tb_anggaran_rka');
$this->db->group_by("kode_warna");
$query=$this->db->get();
return $query->result_array();
}
Related
I'm trying to make a complex query using Laravel Eloquent. I know how to do it using raw SQL query, but I don't have any idea how to do it using Eloquent.
Here is my SQL query, and it works perfectly:
select *
from students
where exists(select *
from (select student_movements.id AS sm_id, student_movements.direction, student_movements.deleted_at
from student_movements
inner join student_student_movements
on student_movements.id = student_student_movements.student_movement_id
where students.id = student_student_movements.student_id
and student_movements.deleted_at is null
order by student_movements.id desc
limit 1) as last_sm
where last_sm.direction = 1 AND last_sm.date >= 5-5-2022
);
My models have many-to-many relation using student_student_movements table:
Student
public function studentMovements(): BelongsToMany
{
return $this->belongsToMany(
StudentMovement::class,
'student_student_movements',
);
}
StudentMovement
public function students(): BelongsToMany
{
return $this->belongsToMany(
Student::class,
'student_student_movements'
);
}
My goal is to get all Students, who have the last Movement where direction = 1 and the date of the last Movement >= $someDate.
So, my question is: how to translate the SQL query to Eloquent? I saw many similar questions, but they are not helping me.
Thanks for any advice.
Use the whereHas method, then fine tune the sub query inside the closure to your needs.
You can use the whereHas and orWhereHas methods to define
additional query constraints on your has queries.
There is an example like that in laravel documentation
use Illuminate\Database\Eloquent\Builder;
// Retrieve posts with at least one comment containing words like code%...
$posts = Post::whereHas('comments', function (Builder $query) {
$query->where('content', 'like', 'code%');
})->get();
// Retrieve posts with at least ten comments containing words like code%...
$posts = Post::whereHas('comments', function (Builder $query) {
$query->where('content', 'like', 'code%');
}, '>=', 10)->get();
check the documentation here
I have 2 table:
products: id, name
auctions: id, product_id, expired_time
Model product
function getAuctions(){
return $this->hasOne('App\Models\Auction', 'product_id', 'id');
}
How can I do the same as below(auctions.expired_time not working):
Controller
function getProductAuctions(){
return \App\Models\Product::with('getAuctions')->whereHas('getAuctions', function(){})->orderBy('auctions.expired_time', 'asc');
}
Thanks everyone.
You can do it with sortBy() method. That method applies to collections only.
function getProductAuctions(){
$products = \App\Models\Product::all();
return $products->sortBy(function ($product, $key) {
return $product->getAuctions->expired_time;
})
}
This should now sort your products collection by the auctions expired time, if you want reversed order, you can just use sortByDesc() method, rest is the same. Also, in your product model, if you are having hasOne() relationship, rename the function name to getAuction() or even better auction() (singular).
you can use one of these to get sort your result
in your controller
function getProductAuctions(){
return \App\Models\Product::with('getAuctions')->whereHas('getAuctions', function($query){
$query->orderBy('expired_time', 'asc');
})->get();
}
and if you want to sort in your model then just use this
function getAuctions(){
return $this->hasOne('App\Models\Auction', 'product_id', 'id')->orderBy('expired_time', 'asc');
}
and thats all no need to do any thing...your result is already sorted
Thank everyone. I found the answer here and I find it correct: https://laracasts.com/discuss/channels/eloquent/order-by-on-relationship
"When you use the with method the Eloquent makes another query in database to retrieve the related data using whereIn. This is why we can't order by a relation field."
I have an issue where a profile can have many campaigns and also many locations.
The campaigns are linked via a pivot table but my goal is just to return all of the location ids.
Profile:
public function campaigns() {
return $this->hasMany('App\Models\Campaign', 'profile_id', 'id');
}
Campaign:
public function locations() {
return $this->belongsToMany('App\Models\Location')->withPivot('campaign_id', 'location_id');
}
Currently I am solving this by doing
$campaigns = $profile->campaigns;
[Doing a nested foreach loop and placing each ID into the array]
How would I get this via a query?
I've tried
$campaigns = $profile->campaigns()
->with('locations')
->get()
->pluck('location.id');
Well, your goal is to get information from the location, so I'd start your query with that. You can condition your query based on the relationships using the whereHas() method.
This assumes your Location has the campaigns relationship defined, and your Campaign has the profile relationship defined.
$ids = Location::whereHas('campaigns.profile', function ($query) use ($profile) {
return $query->where('id', $profile->id);
})->pluck('id');
You can read more about querying by relationships in the documentation here.
My target is to get collection of books with count of matches book.names in another table without relation
I get collection like this
$books = Books::paginate(20);
What I need now is to get the count of matches like this
SELECT COUNT(*) FROM `posts` WHERE `body` LIKE '%book.name%'
How can I do this with one query and avoiding unnecessary queries for each model, like eager loading
You can do it with eager loading without loading all post. There is a method called withCount
Books.php
public function posts() {
return $this->hasMany(Post::class, 'post_id', 'id');
}
One way to find all post related to book is
$books = Books::withCount(['posts' => function ($query) use($searchTerm) {
$query->where('body', 'like', $searchTerm);
}])->get();
//How to retrieve
$book = $books->first()->posts_count.
You can find more information about withCount on laravel documentation website.
Approach 2: Without Eager Loading
$books = Books::select('*')->addSelect(DB::raw("SELECT COUNT(*) as post_count FROM `posts` WHERE `body` LIKE '%book.name%' ")->get(); //This will return collection with post_count.
Note: Not tested
I have 2 models, a User model and a Post model. I am trying to get a collection of Users that have posted between a certain date range. I am just lost on how to tie the 2 models together. There is a One-to-Many relationship between the two.
User Model:
public function posts()
{
return $this->hasMany('App\Models\Post', 'user_id');
}
So, I want a collection of users where posts are between date 1 & date 2 AND if a user has posts between those dates, I want a collection of those posts. I know I can use whereBetween for a query builder, but can I use that for eloquent? Also, how do I sort the entire User model by the ones that have those posts? How about the filter() method?
$users = Users::all();
$users = $users->filter(function() {
foreach ($users as $user)
{
if ($user->posts->whereBetween(date 1, date 2))
{
return true; //something like that
}
}
});
It's better to eager load your relation model as you wanted and then work with the result. no need to use the if checks.
$users = Users::with(['posts' => function($query) {
$query->whereBetween(date 1, date 2);
}])->get();
More Information: Eager Loading