Laravel Eloquent - pick the biggest by each type - join, max() and group by

bysior :

I'm still learning laravel and eloquent and I have a little problem...

I have a three tables:

Schema::create('fishes', function (Blueprint $table) {
                $table->bigIncrements('id');
                $table->bigInteger('user_id')->unsigned();
                $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
                $table->bigInteger('type_id')->unsigned();
                $table->foreign('type_id')->references('id')->on('fish_types')->onDelete('cascade');
                $table->float('length');
});

Schema::create('fish_types', function (Blueprint $table) {
                $table->bigIncrements('id');
                $table->string('name')->unique();
                $table->string('name_raw')->unique();
});

Schema::create('photos', function (Blueprint $table) {
                $table->bigIncrements('id');
                $table->string('photoable_type');
                $table->string('photoable_id');
                $table->string('path');
});

I have model Fish and relations with fish types and photos. And its work, everything is fine, for example:

$f = Fish::with('photos', 'fishery', 'type')->when($filters['userId'], function ($query) use ($filters) {
    return $query->where('user_id', $filters['userId']);
});

But i want get from db the longest fish of each types who belongs to user, of course with photos (eager loading).

I have mysql question (yeee, thats its bad, but my join in eloquent didnt work:( ):

$sql = "
SELECT id
  FROM fishes f1
  JOIN 
     ( SELECT type_id
            , MAX(`length`) AS pb
          FROM fishes
          where user_id = 6
          GROUP BY type_id
     ) AS f2
    ON f1.type_id = f2.type_id 
   and f2.pb = f1.length 
 where f1.user_id = 6
";

So I have id of the fish - but what's next? Same query "whereIn(Column_name, Array)" ?

$sth = DB::getPdo()->prepare($sql);
$sth->execute();
$quy = $sth->fetchAll(\PDO::FETCH_COLUMN, 0);
$f = Fish::with('photos', 'fishery', 'type')
          ->where('user_id', 6)
          ->whereIn('id', $quy)->get();

shortened Fish Model:

class Fish extends Model
{
    public function type()
    {
        return $this->belongsTo('App\Models\FishType');
    }

    public function fishery()
    {
        return $this->belongsTo('App\Models\Fishery');
    }

    public function photos()
    {
        return $this->morphMany('App\Models\Photo', 'photoable');
    }

    public function user()
    {
        return $this->belongsTo('App\User');
    }
}

Photos Model and migration:

 public function up()
    {
        Schema::create('photos', function (Blueprint $table) {

            $table->bigIncrements('id');
            $table->string('photoable_type');
            $table->bigInteger('photoable_id');
            $table->string('path');

        });
    }


class Photo extends Model
{

    public function photoable()
    {
        return $this->morphTo();
    }
}

Its work generally but maybe I do it wrong? How do it in better way? Can You help me? :)

T.

Ahmed butt :

You are executing two queries but this can be done in one query. Try this

Fish::with('photos', 'fishery', 'type')
    ->join(DB::raw('( SELECT type_id
            , MAX(`length`) AS pb
          FROM fishes
          where user_id = 6
          GROUP BY type_id
     ) AS f2'),function($join){
    $join->on('fishes.type_id','=','f2.type_id')
         ->on('fishes.length','=','f2.pb');
    })
    ->where('user_id', 6)->get();

Instead of

$sql = "
SELECT id
  FROM fishes f1
  JOIN **strong text**
     ( SELECT type_id
            , MAX(`length`) AS pb
          FROM fishes
          where user_id = 6
          GROUP BY type_id
     ) AS f2
    ON f1.type_id = f2.type_id 
   and f2.pb = f1.length 
 where f1.user_id = 6
";

$sth = DB::getPdo()->prepare($sql);
$sth->execute();
$quy = $sth->fetchAll(\PDO::FETCH_COLUMN, 0);
$f = Fish::with('photos', 'fishery', 'type')
          ->where('user_id', 6)
          ->whereIn('id', $quy)->get();

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=26580&siteId=1