Laravel查询构建器-从另一个表中选择前1行

时间:2019-09-18 07:52:03

标签: mysql laravel laravel-query-builder

我有这个适用于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部分。我有运动员的表现表,我只需要选择每个运动员的最佳表现作为他个人的最佳表现。

我试图搜索答案,但是发现的所有答案都包括原始添加原始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;
}

4 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:2)

如果您使用的是原始SQL,则只需MAX对使用GROUP BY的每个运动员进行性能测试。

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),但不确定如何与group by一起使用。

恐怕您不能在查询生成器中避免使用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();

参考:

答案 2 :(得分:0)

您可以按以下方式使用。

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

答案 3 :(得分:0)

您可以像这样使用Eloquent ORM

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