I have two related tables:
projects:
| id | name |
| 1 | Test |
| 2 | Example |
project_dates:
| id | project_id | date |
| 1 | 1 | 2020-02-01 |
| 2 | 1 | 2020-02-10 |
| 3 | 1 | 2020-01-25 |
| 4 | 2 | 2020-01-10 |
| 5 | 2 | 2019-12-15 |
Now for example I would like to get all projects where the first date of project_dates is equal to 2020-01-25. So I tried the following:
$projects = Project::whereHas('dates', function($query) {
$query->whereRaw("MIN(date) = '2020-01-25'");
});
But this returns the following error:
SQLSTATE[HY000]: General error: 1111 Invalid use of group function
which revers to MIN(date). So my question remains how can I get all projects with the first date being equal to 2020-01-25 or any other specific date. From the example above I would expect to get the project with id 1 since the first date of 2 is 2019-12-15
I know that is possible to use a subqueryjoin however I feel like doing 2 queries shouldn't be required.
$firstDates = ProjectDate::groupBy('project_id')
->selectRaw('project_id, MIN(date) as first_date');
Project::joinSub($firstDates, 'first_dates', function($join){
$join->on('first_dates.project_id', '=', 'project.id')
->where('first_date', '=','2020-01-25');
})->get();
You cannot use where aggregate function with groupBy, try to use havingRaw instead:
$projects = Project::whereHas('dates', function($query) {
$query->havingRaw("MIN(date) = ?", ['2020-01-25']);
});
// Or
$projects = Project::whereHas('dates', function($query) {
$query->having(DB::raw("MIN(date)"), '2020-01-25');
});
$projects = Project::whereHas('dates', function($query) {
$query->having(DB::raw("MIN(date)"), '2020-01-25')
->groupBy( 'project_dates.id' ); // For sql_mode=only_full_group_by
});
Related
I am trying to make a Laravel Eloquent query which will find me orders by order number and product name.
I have 3 tables orders, order_details & products.
orders table
id | user_id | order_id | order_cart_id
---------------------------------------------------------
1 | 1 | 123-456-7890 | 1
2 | 1 | 789-456-3210 | 2
order_details table
id | order_id | cart_id | p_id
---------------------------------------------------------
1 | 1 | 1 | 22
2 | 1 | 1 | 42
3 | 1 | 1 | 2
4 | 1 | 1 | 32
5 | 1 | 1 | 423
6 | 2 | 2 | 432
products table
id | p_name
--------------------
1 | ABC
2 | CAD
42 | PRO
22 | XYZ
32 | IND
423 | MP
432 | ETC
Orders Model
public function order_cart_products()
{
return $this->hasManyThrough(\App\Models\Products\Product::class,
\App\Models\Orders\OrderDetail::class,
'cart_id',
'id',
'cart_id','p_id');
}
Order Controller
$orders = Order::where('user_id', auth()->user()->id)
->where('order_id', 'LIKE', '%'.$search.'%')
->with('order_cart_products', function ($query) use ($search) {
$query->orWhere('p_name', 'LIKE', '%'.$search.'%');
})
->get()->toArray();
What I am trying to do is by searching order_id(123-456-7890) I need to get all its details with products in it and if I search via p_name(ABC). I need to get all orders in which ABC has been listed. But I don't understand where am I going wrong am not getting desired output.
Try something like below:
$orders = Order::with('order_cart_products')
->where('user_id',auth()->user()->id)
->where(function ($query) use ($search) {
$query->where('order_id', 'LIKE', '%'.$search.'%')
->orWhereHas('order_cart_products', function ($query) use ($search) {
$query->where('p_name', 'LIKE', '%'.$search.'%')
})
})
->get();
If the selected dates ($postFr, $postTo) are within defined periods, I want to list the related products. So can I do something like the following example?
example:
$q->whereBetween('start_date', array($postFr, $postTo));
$q->orWhereBetween('end_date', array($postFr, $postTo));
//Could there be a similar use like this???;
$q->whereBetween(array(start_date, end_date), $postFr);
$q->orWhereBetween(array(start_date, end_date), $postTo);
Detailed explanation:
I have a periods table like this
periods
| id | start_date | end_date | product_id |
|------|--------------|------------|------------|
| 1 | 2021-02-19 | 2021-03-21 | 1 |
| 2 | 2021-02-19 | 2021-03-21 | 2 |
| 3 | 2021-02-19 | 2021-03-21 | 3 |
| 4 | 2021-02-19 | 2021-03-21 | 2 |
and I have a products table like this
products
| id | name |
|-------|-----------|
| 1 | pro1 |
| 2 | pro2 |
| 3 | pro3 |
The relevant codes on my model page are as follows
public $belongsTo = [
'relationPeriod' => [
'Model->periods table',
'key' => 'id',
'otherKey' => 'product_id',
]
]
$query->whereHas('relationPeriod', function($q) use ($postFr, $postTo){
$q->whereBetween('start_date', array($postFr, $postTo]));
$q->orWhereBetween('end_date', array($postFr, $postTo));
});
it works
$q->whereDate('start_date', '<=', $postFr);
$q->whereDate('end_date', '>=', $postFr);
$q->orWhereDate('start_date', '<=', $postTo);
$q->whereDate('end_date', '>=', $postTo);
This will work:
$start_date = '2021-01-01';
$end_date = '2021-02-01';
$filter = Atom_juice_data_history::whereBetween('created_at',[$start_date, $end_date])
->where('atom_juice_data_id',$product_id)
->orderBy('created_at', 'ASC')
->get();
This is reference url
https://medium.com/#sectheater/how-to-use-laravel-wherebetween-method-elegantly-20a50f3b0a2a
I have this following 2 tables:
Table: Products
+----+---------+-------------+
| id | fn_id | created_at |
+----+---------+-------------+
| 1 | 4 | SOME TIME |
| 2 | 5 | SOME TIME |
| 3 | 6 | SOME TIME |
| 4 | 10 | SOME TIME |
| 5 | 10 | SOME TIME |
+----+---------+-------------+
Table Fn
+----+---------+-------------+
| id | fn_id | created_at |
+----+---------+-------------+
| 1 | 10 | SOME TIME |
| 2 | 11 | SOME TIME |
| 3 | 12 | SOME TIME |
| 4 | 14 | SOME TIME |
+----+---------+-------------+
And a User Input which is giving me a timestamp ($user_timestamp).
Now I need to get all produtcs, where
products.fn_id is 10
fn.fn_id is 10
fn.created == $user_timestamp
The products model has this relation:
public function fn() {
return $this->hasMany('App\FN', 'fn_id', 'fn_id');
}
Now I've tried multiple things like a where query where I want to check if the fn_id on both are "10" and the created_at value of the fn table is equal to $user_timestamp.
However, I wasn't able to do it.
$products = Products::with('fn')->where('fn.fn_id', function ($query) use ($user_timestamp) {
$query->where([['fn_id', 10],['created_at', $user_timestamp]]);
})->get();
You would have to use whereHas to constrain Products based on fn.
$products = Products::with('fn')->whereHas('fn', function($q) use($user_timestamp){
$q->where('fn_id', 10)->where('created_at', $user_timestamp);
})->get();
try this
$id_to_search=10;
$products = Products::with('fn')->where('fbn_id',$id_to_search)->whereHas('fn', function($q) use($user_timestamp,$id_to_search){
$q->where('fn_id', $id_to_search)->where('created_at', $user_timestamp);
})->get();
I'm doing a Laravel query to query a list of elements that his relationship is grater than 0.
The table concerts:
| ID | NAME |
|----|-----------|
| 1 | Concert A |
| 2 | Concert B |
| 3 | Concert C |
And the Position table.
| ID | concert_id | user_id | Content |
|----|----------------|------------|----------|
| 1 | 1 | 1 | xxx |
| 2 | 1 | 2 | yyy |
| 3 | 3 | 1 | zzz |
| 4 | 3 | 2 | www |
| 5 | 1 | 3 | xyx |
| 6 | 3 | 3 | rer |
The query that I need to do is, get the concerts where their position has in the content a value like $some_query$.
The code I've is the following:
$result = $this->model->whereHas('positions')
->with(['positions' => function ($query) {
$query->where('content', 'like', "%{$content}%");
}])->get();
But as far as I can tell, this will bring all the concerts, and also this is going to bring only the positions that has the desired content.
So I've two problems, the first one is I need to get the concerts that his queried positions are greather than 0.
And the second one is that also I need to bring all the positions, not only the queried ones.
Basically the query is just a way to know which concerts I need to bring.
Is there possible to achieve this on a single query?
You'll have to move your query to the whereHas.
If I understood well, this is what you want:
$result = $this->model
// Take the Concerts that has positions with a similar content
->whereHas('positions', function ($query) use ($content) {
$query->where('content', 'like', "%{$content}%");
})
// Take (all) the Positions of these concerts
->with('positions')
->get();
messages Table
+----+----------+
| id | text |
+----+----------+
| 1 | message1 |
| 2 | message2 |
+----+----------+
tags table
+----+-----------+
| id | name |
+----+-----------+
| 1 | valentine |
| 2 | funny |
| 3 | santa |
+----+-----------+
message_tag
+----+------------+--------+
| id | message_id | tag_id |
+----+------------+--------+
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 2 | 2 |
+----+------------+--------+
I have written this query so far to get all messages but i cant return the
message where tag_id = 1;
Message::with([
'tags'=>function($q){
$q->select("name","tag_id");
}
])->select("id", "text")->paginate(10);
i have used where clause inside function($q){$q->where('tag_id',1)}. but it didn't worked.
You have to include use Illuminate\Support\Facades\DB; at the top of class
$tagId = 1;
$return = DB::table('message_tag')
->join('messages', 'messages.id', '=', 'message_tag.message_id')
->join('tags', 'tags.id', '=', 'message_tag.tag_id')
->where("message_tag.tag_id", "=", $tagId)
->select('messages.text', 'tags.text')
->get();
Try using whereHas(), assuming you set a many-to-many relationship properly:
$tag = 'Madhab452';
$messages = Message::whereHas('tags', function ($query) use ($tag) {
$query->where('name', '=', $tag)
->select('name', 'tag_id');
})->get();