Get data between date from 2 field in Laravel - laravel

I have data like this:
id | employee_id | absent_type | do_date_start | do_date_end
1 | EMPLOYEE-1 | Absent | 2022-02-14 00:00:00 | 2022-02-18 00:00:00
What I want to do is to get data between field do_date_start and do_date_end.
Case example using data above:
Start Date | End date | Expected Result
2022-02-14 | 2022-02-18 | Data Found
2022-02-13 | 2022-02-19 | Data Found
2022-02-15 | 2022-02-17 | Data Found
2022-02-13 | 2022-02-17 | Data Found
2022-02-19 | 2022-02-20 | Data Not Found
2022-02-12 | 2022-02-13 | Data Not Found
So as long as the date between do_date_start and do_date_end is between filter start date and end date it still getting the data, if not it won't getting the data.
I've tried like this:
DB::table('attendance_absent as absent')
->where(function($query) use ($start_date, $end_date){
$query->where('absent.do_date_start', '<=', $start_date)
->where('absent.do_date_end', '>=', $end_date)
->orWhere(function ($q) use($start_date, $end_date) {
$q->where('absent.do_date_start', '>=', $start_date)
->where('absent.do_date_end', '<=', $end_date)
->orWhere(function ($k) use ($start_date, $end_date) {
$k->where('absent.do_date_start', '>=', $start_date)
->where('absent.do_date_end', '>=', $end_date)
->orWhere(function ($l) use ($start_date, $end_date) {
$l->where('absent.do_date_start', '<=', $start_date)
->where('absent.do_date_end', '<=', $end_date);
});
});
});
})
->get();
When I tested my code using case example above, the result is like this:
Start Date | End date | Expected Result | Correct?
2022-02-14 | 2022-02-18 | Data Found | Yes
2022-02-13 | 2022-02-19 | Data Found | Yes
2022-02-15 | 2022-02-17 | Data Found | Yes
2022-02-13 | 2022-02-17 | Data Found | Yes
2022-02-19 | 2022-02-20 | Data Not Found | No
2022-02-12 | 2022-02-13 | Data Not Found | No
Somehow I still getting the data even though the data is outside date range, I don't know what's wrong with my code. Any help would be very helpful for me, thanks

I came up with a code in Eloquent that I think works with your situation. Not sure how you can do this with DB facade. But here's the code:
$period = ['2022-02-15','2022-02-16'];
return Test::
where(function($q) use ($period) {
return $q->where('do_date_start', '>=', $period[0])->where('do_date_start','<=',$period[1]);
})
->orWhere(function($q) use ($period) {
return $q->where('do_date_end', '>=', $period[0])->where('do_date_end','<=',$period[1]);
})
->orWhere(function($q) use ($period) {
return $q->where('do_date_start', '<=', $period[0])->where('do_date_end','>=',$period[1]);
})
->get();
If it worked for you please inform me so that I can provide more info on how I came up with this.

Related

In Laravel, How to get data from 2 tables data which are not existing in both tables

table 1
| ID | val1 |
| 1 | a |
| 2 | b |
| 3 | c |
table 2
| ID | val1 |
| 1 | a |
| 2 | b |
I need to get the table1 data, which is not on table 2
$users_without_info = DB::table('users')->rightJoin('user_infos', 'users.email', '=', 'user_infos.email')
->select('users.*')
->latest()
->get();
I tried this command, doesn't work.
use inner join
$users_without_info = DB::table('users')
->join('user_infos', 'users.email', '!=', 'user_infos.email')
->select('users.*')
->latest()
->get();
if you have models then use relationships with the foreign key then in user model add relation
public function userInfo(){
return $this->hasOne(UserInfo::class);
}
and the query will be
$users_without_info=\App\Models\User::doesntHave('userInfo')->get();
if you don't have foreign key and want to use email as unique identifier then
public function userInfo(){
return $this->hasOne(UserInfo::class,'email','email');
}
Here is the solution,
The issue is in the join statement.
You can try this way to get the table-1(users) data, which is not on table-2(user_infos),
$users_without_info = DB::table('users')
->leftJoin('user_infos', 'users.email', '=', 'user_infos.email')
->whereNull('user_infos.email')
->get();
Hope you will fix it..

Laravel filter date range with date range columns

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

Laravel ORM - filter by name

I'm newer to Laravel and trying to use ORM to filter my results. So in my database I have table one (Developers) and table two (Programs):
Developers
-------------------
ID. | Name |
------|------------
1 | Bluegreen |
2 | Dancer |
3 | Martin |
------|------------
Programs
-------------------------------------
id | developer_id | name |
------|------------------------------
1 | 12 | Program Test |
2 | 3 | Capital |
3 | 2 | Asus |
4 | 2 | Rich |
5 | 5 | Huna |
------|------------------------------
I'm trying to filter by the Program name and my code is filtering by Developer name. I can easily do this in raw sql but I'm trying to learn ORM, for some reason it's like super difficult for me to learn.
Here's my code:
$query = $request->get('search');
$developers = Developer::where('name', 'LIKE', '%'.$query.'%')->with('programs')->get();
I think this code will work.
DB::table('developers')
->join('programs','developers.id','=','programs.developer_id')
->where('programs.name', 'like', '%'.'Capital'.'%')
->select('programs.*','developers.name')
->get();
You can simply do this in a closure function in laravel with relationships. This will filter your record on program name and also developer name.
$developers = Developer::where('name', 'LIKE', '%'.$request->search.'%')
->with(['programs' => function($filter) use ($request) {
$filter->where('name','LIKE','%'.$request->search.'%');
}])->get();
If you want to only filter by program name then you can do it in this way
$developers = Developer::with(['programs' => function($filter) use ($request) {
$filter->where('name','LIKE','%'.$request->search.'%');
}])->get();
You can also write a condition if $request->search is empty then return all data. If it is not empty then only return the filtered data. I am just simply doing it but you can optimize the query later.
if($request->search != '')
$developers = Developer::with(['programs' => function($filter) use ($request) {
$filter->where('name','LIKE','%'.$request->search.'%');
}])->get();
else
$developers = Developer::with('programs')->get();

Laravel eloquent whereHas where first date equals a specific date

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
});

Fetching a single table data in nested style in Laravel

I am asked to load data from a single table like the following:
=================================
|id |dept | response | created_at |
=================================
|1 |FO | GOOD | 2018-05-20 |
|2 |FO | GOOD | 2018-05-20 |
|3 |IT | GOOD | 2018-05-20 |
|4 |FO | BAD | 2018-05-20 |
|5 |IT | GOOD | 2018-05-20 |
|6 |LO | BAD | 2018-05-20 |
|7 |IT | GOOD | 2018-05-20 |
|8 |IT | GOOD | 2018-05-21 |
|9 |LO | GOOD | 2018-05-21 |
=================================
they want me to display only records created_at 2018-05-20. and the desired output display in blade is like this:
FO
GOOD 2
BAD 1
IT
GOOD 3
BAD 0
LO
GOOD 0
BAD 1
when I use select distinct, it displays only one row of response data (only GOOD). The same thing happens when I use groupBy
here are my current codes:
Controller:
$date = new Carbon('2018-05-20');
$result = Result::select('dept', 'response')->where('created_at', '=', $date->toDateString())->groupby('dept')->get();
blade:
#foreach($result as $result)
{{$result->dept}}</BR>
{{$result->response}}</br></br>
#endforeach
The output I get:
FO
GOOD
IT
GOOD
LO
GOOD
I don't do the count yet because I still get this undesired result.
Is there a way to achieve the desired request with that single table?
EDIT I:
Based on Yrv16's answer, my controller goes like this:
namespace App\Http\Controllers;
use App\Result;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;
public function index()
{
$date = new Carbon('2018-05-20');
$results = Result::select('dept', 'response', \DB::raw('COUNT(*) as count'))
->where('created_at', '=',$date->toDateString())
->groupby('dept','response')
->get();
$results = $results->groupBy('dept');
return view('result.index', compact ('results'));
}
and my blade:
#foreach($results as $result)
{{$result->dept}}</BR>
{{$result->response}}</br></br>
#endforeach
this gives me an empty page. but when i change this where('created_at', '=', $date->toDateString()) to where('created_at', '>=', $date->toDateString()) i get this error Property [dept] does not exist on this collection instance.
Use groupBy for two columns dept, response:
$date = new Carbon('2018-05-20');
$results = Result::select('dept', 'response', \DB::raw('COUNT(*) as count'))
->where('created_at', '=',$date->toDateString())
->groupby('dept','response')
->get();
Also result collection you can groupBy('dept') in order to display it like you want:
$results = $results->groupBy('dept');
Blade:
#foreach($results as $dept => $result)
{{$dept}}</BR>
#foreach($result as $item)
{{$item->response}} {{ $item->count }}
#endforeach
#endforeach
You can use collection manipulation for that:
$results = Result::where('created_at', '2018-05-20')
->get()
->groupBy('dept')
->map(function ($item) {
return $item->groupBy('response')->map(function ($responses) {
return $responses->count();
});
});
It will give you the following results:
print_r($results->toArray());
Array (
[FO] => Array (
[GOOD] => 2
[BAD] => 1
)
[IT] => Array (
[GOOD] => 3
)
[LO] => Array (
[BAD] => 1
)
)

Resources