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

Rooduef's avatar

Get model by min() one of fields grouped by another field

Hi everyone.

Please help me to solve the next problem. I have two tables in the database - events and schedules.

Their schemes:

              Table "public.events"
       Column       |              Type              |                  
--------------------+--------------------------------+
 id                 | bigint                         |
 name               | character varying(255)         |
 description        | text                           |
 duration           | character varying(255)         |
 created_at         | timestamp(0) without time zone |
 updated_at         | timestamp(0) without time zone |



              Table "public.schedules"
      Column      |              Type              | 
------------------+--------------------------------+
 id               | bigint                         |
 event_id         | integer                        |
 date             | timestamp(0) without time zone |
 price            | character varying(255)         |
 created_at       | timestamp(0) without time zone |
 updated_at       | timestamp(0) without time zone |

schedules.event_id is the foreign key references on events.id

I need to fetch the nearest schedule for each event. With raw SQL I can do it with this query:

SELECT s.*
FROM schedules rs
INNER JOIN
  (SELECT event_id,
          min(date) min_date
   FROM schedules
   GROUP BY event_id
   ) s1 ON s1.event_id = s.event_id
WHERE s1.min_date = s.date

But how can I do this with Eloquent?

Thanks for help.

0 likes
6 replies
jlrdw's avatar

I would consider using as is with db facade, for an example see:

https://laracasts.com/discuss/channels/laravel/sql-native-to-query-builder

Give me minute, for example of eloquent query:

Not your data, just an eloquent query example:

$quy = Powner::query()->leftJoin('dc_pets', 'dc_powners.ownerid', '=', 'dc_pets.ownerid')
                ->select('dc_powners.ownerid', 'dc_powners.oname')
                ->selectRaw('count(dc_pets.petid) as countOfPets')
                ->groupby('dc_powners.ownerid')
                ->orderby('dc_powners.oname')
                ->get();

Results basically give:

ownerid, oname, countOfPets

Like:

5|Bob|3
4|Greg|9
2|Rob|1

Just use a little trial and error to work it out.

Rooduef's avatar

Thank you, but I see that you join another table while I need to join a result of subquery on the same table. Sorry, but I can't imagine how I can apply your approach to my problem.

Can you give a deeper explanation?

Rooduef's avatar

I tried to do this:

$s1 = \DB::table('schedules')
    ->selectRaw('event_id, min(datetime) as min_date')
    ->groupBy('event_id');

$s = \DB::table('schedules as s')
    ->joinSub($s1, 's1', function (Builder $join) {
        $join->on('s.event_id', '=', 's1.event_id');
    })
    ->where('s.datetime', '=', 's1.min_date')
    ->get('s.*');

But got the error:

Illuminate\Database\QueryException : SQLSTATE[22007]: Invalid datetime format: 7 ERROR: invalid input syntax for type timestamp: "s1.min_date"

Rooduef's avatar
Rooduef
OP
Best Answer
Level 1

I solved this problem simpler:

$schedules = Schedule::selectRaw('DISTINCT ON (event_id) *')
    ->orderBy('event_id')
    ->orderBy('date')
    ->get();

But, as far as I know, this query will work only with PostgreSQL.

Please or to participate in this conversation.