[英]Is it possible to run a join on a variable created by a sub-query?
Right now I am running a sub-query to get the most recent status for a server, this sub-query is returning through the variable last_status
. 现在,我正在运行一个子查询以获取服务器的最新状态,该子查询通过变量last_status
返回。
//This is ran when WithLastStatusDate() is called
$query->addSubSelect('last_status', ServerStatus::select('status_id')
->whereRaw('server_id = servers.id')
->latest()
);
$servers = Server::WithLastStatusDate()
->OrderBy('servers.id', 'desc')
->where('servers.isPublic', '=', 1)
->get();
What I am trying to do now is do a join on this so that it gives me the actual name of the status based on the result of this query in the statuses table. 我现在想做的就是对此进行联接,以便根据状态表中此查询的结果为我提供状态的实际名称。 I have tried to do a simple left join but am getting the error that the last_status column isn't found. 我试图做一个简单的左联接,但是却收到找不到last_status列的错误。
$servers = Server::WithLastStatusDate()
->OrderBy('servers.id', 'desc')
->where('servers.isPublic', '=', 1)
->leftjoin('statuses','servers.last_status', '=', 'statuses.id')
->get();
Can anyone point me in the right direction on how to accomplish this? 谁能为我指出正确的方向呢?
EDIT:: 编辑::
Server Table: 服务器表:
Schema::create('servers', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->increments('id');
$table->string('name');
$table->string('url');
$table->boolean('isPublic');
$table->timestamps();
});
Server_statuses Table: Server_statuses表:
Schema::create('server_statuses', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->increments('id');
$table->integer('server_id')->unsigned();
$table->foreign('server_id')->references('id')->on('servers')->onDelete('cascade');
$table->integer('status_id')->unsigned();
$table->foreign('status_id')->references('id')->on('statuses');
$table->timestamps();
});
statuses table: 状态表:
Schema::create('statuses', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->increments('id');
$table->string('key');
$table->string('status');
$table->timestamps();
});
What $servers looks like after sub-query: 子查询后,$ servers是什么样的:
Raw SQL of query: 查询的原始SQL:
select `servers`.*, (select `status_id` from `server_statuses` where server_id = servers.id order by `created_at` desc limit 1) as `last_status` from `servers` where `servers`.`isPublic` = '1' order by `servers`.`id` desc
EDIT 2:: 编辑2 ::
$servers = DB::table('servers as sv')
->join('server_statuses as ss', 'sv.id', '=', 'ss.server_id')
->join('statuses as st', 'ss.status_id', '=', 'st.id')
->WithLastStatus()
->OrderBy('servers.id', 'desc')
->where('servers.isPublic', '=', 1)
->get();
Combine LEFT JOINs with a subquery WHERE clause: 将LEFT JOIN与子查询WHERE子句组合:
$servers = Server::select('servers.*', 'statuses.status as status_name')
->leftJoin('server_statuses', function($join) {
$join->on('server_statuses.server_id', '=', 'servers.id')
->where('server_statuses.id', function($query) {
$query->select('id')
->from('server_statuses')
->whereColumn('server_id', 'servers.id')
->latest()
->limit(1);
});
})
->leftJoin('statuses', 'statuses.id', '=', 'server_statuses.status_id')
->where('servers.isPublic', '=', 1)
->orderBy('servers.id', 'desc')
->get();
Since i'm not sure what exactly do you want to get from your query i going with a long solution and add some examples. 由于我不确定您想从查询中得到什么,我将提供一个长解决方案并添加一些示例。 With these tables you should have these models: Server model: 使用这些表,您应该具有以下模型:服务器模型:
class Server extends Model {
public function statuses() {
return $this->belongsToMany(Status::class, 'server_statuses');
}
}
Status model: 状态模型:
class Status extends Model {
public function servers() {
return $this->belongsToMany(Server::class, 'server_statuses');
}
}
Examples: Get last status of server: 示例:获取服务器的最新状态:
Server::find($serverId)->statuses()->latest()->first()->status;
Get all server statuses: 获取所有服务器状态:
Server::find($serverId)->statuses;
Get server's specific status: 获取服务器的特定状态:
Server::find($serverId)->statuses()->where('status', 'SomeStatus')->get();
Get servers that have specific status: 获取具有特定状态的服务器:
Server::whereHas('statuses', function ($join) use ($status) {
return $join->where('status', $status);
})->get();
Hope you find your answer. 希望你找到答案。
As far as I understand, both your Server
and Status
models have a OneToMany
relationship to ServerStatus
. 据我了解,您的Server
模型和Status
模型都与ServerStatus
具有OneToMany
关系。 In this case, you could fake a OneToOne
relationship on your Server
model which is selected as the latest row of serverStatuses()
: 在这种情况下,您可以在Server
模型上伪造一个OneToOne
关系,该关系被选择为serverStatuses()
的最新行:
class Server
{
public function serverStatuses()
{
return $this->hasMany(ServerStatus::class, 'server_id', 'id');
}
public function latestServerStatus()
{
return $this->hasOne(ServerStatus::class, 'server_id', 'id')
->latest(); // this is the most important line of this example
// `->orderBy('created_at', 'desc')` would do the same
}
}
class ServerStatus
{
public function server()
{
return $this->belongsTo(Server::class, 'server_id', 'id');
}
public function status()
{
return $this->belongsTo(Status::class, 'status_id', 'id');
}
}
class Status
{
public function serverStatuses()
{
return $this->hasMany(ServerStatus::class, 'status_id', 'id');
}
}
You can then also eager load the latest status for your servers as well as the status itself: 然后,您也可以急于加载服务器的最新状态以及状态本身:
Server::with('latestServerStatus.status')->get();
Please be aware that $server->latestServerStatus
is no collection but one object, just like in a normal OneToOne
relation. 请注意, $server->latestServerStatus
不是集合,而是一个对象,就像在普通的OneToOne
关系中一样。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.