php—是否可以对子查询创建的变量运行联接?

1tuwyuhd  于 2021-06-24  发布在  Mysql
关注(0)|答案(3)|浏览(309)

现在我运行一个子查询来获取服务器的最新状态,这个子查询通过变量返回 last_status .

  1. //This is ran when WithLastStatusDate() is called
  2. $query->addSubSelect('last_status', ServerStatus::select('status_id')
  3. ->whereRaw('server_id = servers.id')
  4. ->latest()
  5. );
  6. $servers = Server::WithLastStatusDate()
  7. ->OrderBy('servers.id', 'desc')
  8. ->where('servers.isPublic', '=', 1)
  9. ->get();

我现在要做的是对它执行一个join,这样它就会根据statuses表中的查询结果给出状态的实际名称。我试着做一个简单的左连接,但得到的错误是没有找到最后一个\u status列。

  1. $servers = Server::WithLastStatusDate()
  2. ->OrderBy('servers.id', 'desc')
  3. ->where('servers.isPublic', '=', 1)
  4. ->leftjoin('statuses','servers.last_status', '=', 'statuses.id')
  5. ->get();

有谁能给我指出正确的方向来实现这个目标吗?
编辑:
服务器表:

  1. Schema::create('servers', function (Blueprint $table) {
  2. $table->engine = 'InnoDB';
  3. $table->increments('id');
  4. $table->string('name');
  5. $table->string('url');
  6. $table->boolean('isPublic');
  7. $table->timestamps();
  8. });

服务器状态表:

  1. Schema::create('server_statuses', function (Blueprint $table) {
  2. $table->engine = 'InnoDB';
  3. $table->increments('id');
  4. $table->integer('server_id')->unsigned();
  5. $table->foreign('server_id')->references('id')->on('servers')->onDelete('cascade');
  6. $table->integer('status_id')->unsigned();
  7. $table->foreign('status_id')->references('id')->on('statuses');
  8. $table->timestamps();
  9. });

状态表:

  1. Schema::create('statuses', function (Blueprint $table) {
  2. $table->engine = 'InnoDB';
  3. $table->increments('id');
  4. $table->string('key');
  5. $table->string('status');
  6. $table->timestamps();
  7. });

子查询后$servers的外观:

查询的原始sql:

  1. 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

编辑2::

  1. $servers = DB::table('servers as sv')
  2. ->join('server_statuses as ss', 'sv.id', '=', 'ss.server_id')
  3. ->join('statuses as st', 'ss.status_id', '=', 'st.id')
  4. ->WithLastStatus()
  5. ->OrderBy('servers.id', 'desc')
  6. ->where('servers.isPublic', '=', 1)
  7. ->get();
zhte4eai

zhte4eai1#

因为我不确定你到底想从你的查询中得到什么,所以我将给出一个很长的解决方案并添加一些示例。有了这些表,您应该有以下模型:服务器模型:

  1. class Server extends Model {
  2. public function statuses() {
  3. return $this->belongsToMany(Status::class, 'server_statuses');
  4. }
  5. }

状态模型:

  1. class Status extends Model {
  2. public function servers() {
  3. return $this->belongsToMany(Server::class, 'server_statuses');
  4. }
  5. }

示例:获取服务器的最后状态:

  1. Server::find($serverId)->statuses()->latest()->first()->status;

获取所有服务器状态:

  1. Server::find($serverId)->statuses;

获取服务器的特定状态:

  1. Server::find($serverId)->statuses()->where('status', 'SomeStatus')->get();

获取具有特定状态的服务器:

  1. Server::whereHas('statuses', function ($join) use ($status) {
  2. return $join->where('status', $status);
  3. })->get();

希望你能找到答案。

展开查看全部
6vl6ewon

6vl6ewon2#

据我所知,你们两个 Server 以及 Status 模型有一个 OneToMany 关系 ServerStatus . 在这种情况下,你可以假装 OneToOne 你的关系 Server 被选为最新一行的模型 serverStatuses() :

  1. class Server
  2. {
  3. public function serverStatuses()
  4. {
  5. return $this->hasMany(ServerStatus::class, 'server_id', 'id');
  6. }
  7. public function latestServerStatus()
  8. {
  9. return $this->hasOne(ServerStatus::class, 'server_id', 'id')
  10. ->latest(); // this is the most important line of this example
  11. // `->orderBy('created_at', 'desc')` would do the same
  12. }
  13. }
  14. class ServerStatus
  15. {
  16. public function server()
  17. {
  18. return $this->belongsTo(Server::class, 'server_id', 'id');
  19. }
  20. public function status()
  21. {
  22. return $this->belongsTo(Status::class, 'status_id', 'id');
  23. }
  24. }
  25. class Status
  26. {
  27. public function serverStatuses()
  28. {
  29. return $this->hasMany(ServerStatus::class, 'status_id', 'id');
  30. }
  31. }

然后还可以加载服务器的最新状态以及状态本身:

  1. Server::with('latestServerStatus.status')->get();

请注意 $server->latestServerStatus 不是集合而是一个对象,就像普通的 OneToOne 关系。

展开查看全部
huwehgph

huwehgph3#

将左联接与子查询where子句组合:

  1. $servers = Server::select('servers.*', 'statuses.status as status_name')
  2. ->leftJoin('server_statuses', function($join) {
  3. $join->on('server_statuses.server_id', '=', 'servers.id')
  4. ->where('server_statuses.id', function($query) {
  5. $query->select('id')
  6. ->from('server_statuses')
  7. ->whereColumn('server_id', 'servers.id')
  8. ->latest()
  9. ->limit(1);
  10. });
  11. })
  12. ->leftJoin('statuses', 'statuses.id', '=', 'server_statuses.status_id')
  13. ->where('servers.isPublic', '=', 1)
  14. ->orderBy('servers.id', 'desc')
  15. ->get();

相关问题