Laravel 查询生成器 - select 来自另一个 table 的前 1 行

Laravel Query builder - select top 1 row from another table

我有一个 MySQL 的 SQL 查询,效果很好。但是我需要使用查询生成器重写它并且需要完全避免 DB::raw() 因为开发数据库与生产数据库不同。我知道远非理想,但不幸的是它就是这样。

SELECT athletes.*, 
     (
         SELECT performance
         FROM performances
         WHERE athletes.id = performances.athlete_id AND performances.event_id = 1
         ORDER BY performance DESC
         LIMIT 0,1
     ) AS personal_best
FROM athletes
ORDER BY personal_best DESC
Limit 0, 100

我正在努力重写 personal_best 部分。我有 table 个运动员的表现,我只需要 select 每个运动员的最佳表现作为他的个人最好成绩。

我试图寻找答案,但我找到的所有答案都包括原始添加原始 SQL。

如有任何想法或提示,我们将不胜感激。

提前致谢!

所以我接受了我可能不得不为此使用 Eloquent,但仍然无法进步。这是我的代码:

class Athlete extends Model
{
    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'athletes';

    /**
     * The primary key associated with the table.
     *
     * @var string
     */
    protected $primaryKey = 'id';

    /**
     * Indicates if the model should be timestamped.
     *
     * @var bool
     */
    public $timestamps = false;

    /**
     * Get the performances for the Athelete post.
     *
     * @return HasMany
     */
    public function performances()
    {
        return $this->hasMany('App\EloquentModels\Performance', 'athlete_id');
    }
}

class Performance extends Model
{
    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'performances';

    /**
     * The primary key associated with the table.
     *
     * @var string
     */
    protected $primaryKey = 'id';

    /**
     * Indicates if the model should be timestamped.
     *
     * @var bool
     */
    public $timestamps = false;
}

如果您使用的是原始 SQL,只需使用 GROUP BY.

对每个运动员的表现进行 MAX
SELECT athletes.*, MAX(performance) AS personal_best
FROM athletes
INNER JOIN performances ON athletes.id = performances.athlete_id AND performances.event_id = 1
GROUP BY athletes.id
ORDER BY personal_best DESC
LIMIT 0, 100

Laravel 查询生成器:

DB::table('athletes')
    ->join('performances', 'athletes.id', '=', 'performances.athlete_id')
    ->where('performances.event_id', '=', 1)
    ->groupBy('athletes.id')
    ->orderBy('personal_best', 'desc')
    ->select('athletes.*',DB::raw('MAX(performance) AS personal_best')
    ->limit(100);

Doc 说我们可以做到 max(personal_best) 但不确定如何将其与分组依据一起使用。

恐怕您无法在查询生成器中避免使用 DB::raw,但您可以使用 eloquent model 来达到相同目的,正如 Shaielndra Gupta 所回答的那样。

为此,您可以创建模型和关系。

1. Create Model:
php artisan make:model Athelete
php artisan make:model Performance

2. Create relationship between Athelete and Perforamnce.

Update Athelete.php 

    /**
     * Get the performances for the Athelete post.
     */
    public function performances()
    {
        return $this->hasMany('App\Performance');
    }

3. Get data(didn't verify by myself)
$data = Athelete::with('performances',function ($query) use ($eventId){
    $query->max('performance')
    $query->where('event_id',$eventId)
    $query->orderBy('performance');
})->get();

参考:

您可以像下面这样使用。

$sql1 = "(
         SELECT performance
         FROM performances
         WHERE athletes.id = performances.athlete_id AND performances.event_id = 1
         ORDER BY performance DESC
         LIMIT 0,1
     ) AS personal_best";

$sql2 = "SELECT athletes.*,$sql1          
FROM athletes
ORDER BY personal_best DESC
Limit 0, 100";

$result = DB::select($sql2);

database.php 为开发参数创建一个新连接,例如 mysql_dev。

DB::connection('mysql_dev')->table('athletes')
    ->leftJoin('performances','athletes.id','performances.athlete_id')
    ->where('performances.event_id',1)
    ->groupBy('athletes.id')
    ->orderByDesc('personal_best')
    ->select('athletes.*',DB::raw('MAX(performances.performance) AS personal_best')
    ->paginate(100);

试试这样不生的,

DB::connection('mysql_dev')->table('athletes')
    ->leftJoin('performances','athletes.id','performances.athlete_id')
    ->where('performances.event_id',1)
    ->groupBy('athletes.id')
    ->orderByDesc('performances.performance')
    ->select('athletes.*','performances.performance'
    ->paginate(100);

你可以像这样使用 Eloquent ORM

$data = Athelete::with('performances',function ($query) use ($eventId){
    $query->max('performance')
    $query->where('event_id',$eventId)
    $query->orderBy('performance');
})->get()