首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Laravel雄辩/MySQL如何从每个家长记录的最后一项中获得最后一年的记录?

Laravel雄辩/MySQL如何从每个家长记录的最后一项中获得最后一年的记录?
EN

Stack Overflow用户
提问于 2021-11-30 07:08:07
回答 1查看 401关注 0票数 1

假设我在遗留系统中有以下关系,无法更改它。

  1. 省表(hasMany区)
  2. 地区表(hasMany村)
  3. 乡村桌(hasMany医院)
  4. hospital_types表(hasOne医院)
  5. 医院表(belongsTo hospital_types,hasMany监控)
  6. 监视表(hasMany rateLog)

我想要的是带医院的省份,并对每一家医院进行最后一年的监测。

注:最后一年意味着不是现在的日期,这意味着我们应该取每家医院的最后一次监测日期,然后从该日期开始计算到该日期为止的12个月。

假设A医院上一次被监测是在2020年-11-01年,那么从2020年到11-01年间的所有监测都应该持续到2019-11-01年。其他医院也一样。

已经用Laravel资源实现了,但是有点慢,而且也不知道如何在资源返回数据之后实现orderBy特性,因为我需要基于监视的分页和排序,现在我通过资源来处理它。

目前,我使用的是hasManyThrough关系,在get之后,我将数据传递给资源收集和处理监控的get。但是这样不能实现排序和分页。

代码语言:javascript
运行
复制
$data = Province::with(['districts.hospitalTypes])->get();

然后,我将数据传递给资源并得到监视,但是如何应用排序和分页,因为排序是基于监视的。而且使用资源的速度比急切的加载要慢一些。我正在寻找一种方法来使用那些标准的“急切加载”。

代码语言:javascript
运行
复制
class ProvinceResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'districts' => DistrictResource::collection($this->whenLoaded("districts"))
        ];
    }
}
代码语言:javascript
运行
复制
class DistrictResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'hospitals' => HospitalTypeResource::collection($this->whenLoaded("hospital_types"))
        ];
    }
}
代码语言:javascript
运行
复制
class HospitalTypeResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        $district = $this->village->district;
        
        $oneLastYearRateLog = $this->hospital->last12MonthRageLogs();
        $rateLogCount = $oneLastYearRateLog->count();

        $oneLastYearMonitoringCount = $this->hospital->last12MonthMonitors()->count();

        return [
            "id" => $this->hospital->id,
            "code" => $this->code,
            "name" => $this->name,
            "overallRating"=> $rateLogCount == 0 ? 0 : $oneLastYearRateLog->sum('rate') / $rateLogCount,
            "ratingsCount" => $oneLastYearMonitoringCount
        ];
    }
}

下面是我在医院的关系模式来做监测。

代码语言:javascript
运行
复制
class Hospital extends Model
{
 /**
 * Get hospital monitors
 */
public function monitors()
{
    return $this->hasMany(Monitoring::class, 'hospital_id', 'id');
}

public function last12MonthMonitors()
{
    $lastMonitoring = $this->lastMonitoring();
    if($lastMonitoring) {
        return $this->monitors()->whereRaw('monitoring_date >= "'. $lastMonitoring->monitoring_date.'" - INTERVAL 12 month');
    }
    return $this->monitors();
}

private function lastMonitoring()
{
    return $this->monitors()->select('monitoring_date')->latest('monitoring_date')->first();
}

/**
 * Get rate logs
 */
public function rateLogs()
{
    return $this->hasManyThrough(RateLog::class, Monitoring::class, 'hospital_id')
        ->where('rate', '!=', 'NA');
}

/**
 * Get last 12 rate logs
 */
public function last12MonthRageLogs()
{
    $lastMonitoring = $this->lastMonitoring();
    if($lastMonitoring) {
        return $this->rateLogs()->whereRaw('monitoring.monitoring_date >= "'.$lastMonitoring->monitoring_date.'" - INTERVAL 12 month');
    }
    return $this->rateLogs();
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-11-30 10:07:50

您似乎并不急于加载hospital关系。我首先要添加以下内容,这样您就不必为每个HospitalType运行一个查询了

代码语言:javascript
运行
复制
$data = Province::with(['districts.hospitalTypes.hospital'])->get();

我认为您的查询可能运行得稍微慢一点的原因之一是因为您的lastMonitoring检查。首先,这个查询将为每个Hospital运行,其次,您似乎没有存储/缓存该值,因此它实际上将是查询两次。

如果您更新到Laravel 8(minv8.4.2),您将能够为您的有多种关系之一方法使用lastMonitoring方法,例如:

代码语言:javascript
运行
复制
public function latestMonitoring()
{
    return $this->hasOne(Monitoring::class)->latestOfMany('monitoring_date');
}

然后你就可以热切地去加载这种关系了:

代码语言:javascript
运行
复制
$data = Province::with(['districts.hospitalTypes.hospital.latestMonitoring'])->get();

您还需要更新HospitalType模型中的其他一些方法:

代码语言:javascript
运行
复制
public function monitors()
{
    return $this->hasMany(Monitoring::class, 'hospital_id', 'id');
}

/**
 * Get rate logs
 */
public function rateLogs()
{
    return $this->hasManyThrough(RateLog::class, Monitoring::class, 'hospital_id')
        ->where('rate', '!=', 'NA');
}

public function latestMonitoring()
{
    return $this->hasOne(Monitoring::class, 'hospital_id', 'id')->latestOfMany('monitoring_date');
}

public function last12MonthMonitors()
{
    return $this->monitors()->when($this->latestMonitoring, function ($query) {
        $query->where('monitoring_date', '>=', $this->latestMonitoring->monitoring_date->subYear());
    });
}

/**
 * Get last 12 rate logs
 */
public function last12MonthRageLogs()
{
    return $this->rateLogs()->when($this->latestMonitoring, function ($query) {
        $query->where('monitoring.monitoring_date', '>=', $this->latestMonitoring->monitoring_date->subYear());
    });
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70165525

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档