Laravel Eloquent/QueryBuilder 多个嵌套选择

Laravel Eloquent/QueryBuilder Multiple Nested Selects

我如何在 eloquent/query 生成器中编写这样的查询?有多个嵌套 select 语句并带有连接的查询。 任何帮助将不胜感激。

    Select
          s.user_id,
          s.user_name,
          s.`user_firstname`,
          s.`user_lastname`,
          s.user_photo,
          max_rank_timestamp,
          max_friend_timestamp
    FROM
          (
            SELECT
              Users.user_id,
              Users.`user_name`,
              Users.`user_firstname`,
              Users.`user_lastname`,
              `Users`.`user_photo`,
              MAX(Ranks.rank_timestamp) AS max_rank_timestamp
            FROM
              `Users`
              LEFT JOIN Ranks ON Ranks.user_id = Users.user_id
            WHERE
              Users.user_is_active = 1
            GROUP BY
              Users.user_id
          ) s
          LEFT JOIN (
                      SELECT
                        Users.user_id,
                        MAX(Relationship.timestamp) AS max_friend_timestamp
                      FROM
                        `Users`
                        INNER JOIN Relationship ON Relationship.user_one_id = Users.user_id
                      WHERE
                        Users.user_is_active = 1
                      GROUP BY
                        Users.user_id
                    ) p ON s.user_id = p.user_id
      ) t
    ORDER BY
      `user_name` ASC

用户模型

public function ranks(){
    return $this->hasMany('App\Rank','user_id','user_id');
}

public function relationships(){
    return $this->hasMany('App\Relationship','user_one_id','user_id');
}

排名模型

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

关系模型

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

您可以这样做的一种方法是将以下范围添加到您的 User 模型中:

public function scopeWithMaxRankTimestamp(Builder $query)
{
    if (is_null($query->getQuery()->columns)) {
        $query->select([$query->getQuery()->from . '.*']);
    }

    $relation = Relation::noConstraints(function () {
        return $this->ranks();
    });

    $q = $this->ranks()->getRelationExistenceQuery(
        $relation->getRelated()->newQuery(), $query, new Expression('MAX(rank_timestamp)')
    );

    $query->selectSub($q->toBase(), 'max_rank_timestamp');
}

public function scopeWithMaxFriendTimestamp(Builder $query)
{
    if (is_null($query->getQuery()->columns)) {
        $query->select([$query->getQuery()->from . '.*']);
    }

    $relation = Relation::noConstraints(function () {
        return $this->relationships();
    });

    $q = $this->relationships()->getRelationExistenceQuery(
        $relation->getRelated()->newQuery(), $query, new Expression('MAX(timestamp)')
    );

    $query->selectSub($q->toBase(), 'max_friend_timestamp');
}

上面假设 Ranks table 的关系是 ranks()Relationship table 的关系是 relationships()

要使上述工作正常,您还需要将以下 use 语句添加到 class 的顶部:

use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Database\Query\Expression;

然后你可以像这样使用你的结果:

$users = User::withMaxRankTimestamp()
    ->withMaxFriendTimestamp()
    ->where('user_is_active', 1)
    ->orderBy('user_name')
    ->get();

希望对您有所帮助!