Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

sin2san's avatar

How to get value based on hasmany table first value?

I am having two tables batches and batch_schedules. Batches is having hasmany relationship with batch_schedules. Batches table consists of batch details and batch_schedules consists of dates & times of the schedules.

I am trying to filter batches based on batch_schedules dates. How to filter based on first date of each batches?

For Eg: Consider Batches Table having 1 row

id | Name
3	| AA1

Conside Batch_schedules having 3 rows

id | Batch_id | Date | Time
2   |  3 | 2021/04/09 | 10:00 AM
3    | 3  | 2021/04/10 | 10:00 AM
4   | 3   | 2021/04/11 | 10:00 AM

id 2 in batch_Schedules is the starting date. So I need to filter based on starting date. If my filter start date is 2021/04/08 and end date is 2021/04/11 it should display batches (id: 3).

If my filter start date is 2021/04/10 and end date is 2021/04/11 it should not display anything as there is no start date in between the filtered dates.

0 likes
13 replies
jlrdw's avatar

You will need a where clause, and an orderby if you want to order it.

neilstee's avatar

@sin2san

$startDate = '2021/04/08';
$endDate = '2021/04/11';

$batch = Batch::with(['batchSchedules' => function($query) use ($startDate, $endDate){
	$query->whereBetween('Date', $startDate, $endDate)
		->orderBy('Date', 'desc');
}])->find(3);

And to retrieve the first batchSchedules, do this:

$batch->batchSchedules()->first(); 

Since your batch schedules are hasMany relationship, it will return a collection of BatchSchedules so you need to get the only first item.

sin2san's avatar

@neilstee

This is what I am doing exactly but my concern is I need to return batches based on batch schedule first row value.

neilstee's avatar

@sin2san then just change with to whereHas:

$batch = Batch::whereHas(['batchSchedules' => function($query) use ($startDate, $endDate){
	$query->whereBetween('Date', $startDate, $endDate)
		->orderBy('Date', 'desc');
}])->find(3);
sin2san's avatar
$allData = Batch::whereHas(['schedule' => function($query) use ($aStartDate, $aEndDate){
	$query->whereBetween('date', [$aStartDate, $aEndDate])->orderBy('date', 'desc');
}])->paginate(10);

dd($allData);
ErrorException (E_WARNING)
strpos() expects parameter 1 to be string, array given

I am getting this error.

neilstee's avatar

@sin2san sorry but it should be two parameters not array

$allData = Batch::whereHas('schedule', function($query) use ($aStartDate, $aEndDate){
	$query->whereBetween('date', [$aStartDate, $aEndDate])->orderBy('date', 'desc');
})->paginate(10);

dd($allData);
sin2san's avatar

On trying this it's returning based on all schedule dates not the first date.

neilstee's avatar

@sin2san that's why I told you to run first. or limit it by 1

$allData = Batch::whereHas('schedule', function($query) use ($aStartDate, $aEndDate){
	$query->whereBetween('date', [$aStartDate, $aEndDate])->orderBy('date', 'desc')->limit(1);
})->paginate(10);

dd($allData);
sin2san's avatar

On trying first()

Illuminate \ Database \ QueryException (42S22)
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'batches.id' in 'where clause' (SQL: select * from `batch_schedule` where `batches`.`id` = `batch_schedule`.`batch_id` and `date` between 2021/04/12 and 2021/04/30 and `batch_schedule`.`deleted_at` is null limit 1)

On trying limit(1) it still returns based on all schedule dates.

neilstee's avatar

Also, make sure that $query->whereBetween('date', [$aStartDate, $aEndDate] is correct. Try to debug your code by adding:

DB::enableQueryLog();
// your query here
dd(DB::getQueryLog());

Check if SQL is correct.

sin2san's avatar

It's returning based on all data values from the schedule table not based on first row value.

sin2san's avatar
select * from batches join (
    select * from (
        select *, row_number() over (
            partition by batch_id  
            order by date ASC
        ) as row_num
        from batch_schedule where display = 'Yes'
    ) as d_batch_schedule
    where d_batch_schedule.row_num = 1
) as f_batch_schedule
on batches.id = f_batch_schedule.batch_id
WHERE (f_batch_schedule.date BETWEEN '2021/01/01' AND '2021/04/30')

This query works but how to write in laravel?

Please or to participate in this conversation.