Laravel 查询关联的最后一条记录的 where 子句 table

Laravel query where clause on the last record of the associated table

我正在开发 Laravel 应用程序。我在使用 where 子句查询关联的两个表时遇到问题。这是我的数据库架构。

patients
========
id, name, email, password, created_at

treatments
==========
id, created_at, disease, note, patient_id

treatment_logs
=============
id, status, created_at, treatment_id

我的数据库架构非常简单。现在我想做的是创建一个查询,以获取最后 treatment_logs 状态为 1 的用户的处理。这是我的查询

class Patient extends Model {

    public function intensiveTreatments()
    {
        return $this->treatments()->whereHas('treatment_logs', function ($query) {
            $query->orderBy('id', 'desc')
                ->take(1)
                ->where('status', 1);
        });
    }

}

该查询的问题在于处理日志的最后记录状态是什么并不重要。只要有状态为1的treatment_logs,就会去return记录。但是我只想获取状态为1的最后一个treatment_logs的记录。我怎样才能得到它?

加一个->with('treatment_logs', function($query) { [... same clauses you use in whereHas...] })。发生这种情况是因为您的查询过滤的是治疗而不是治疗日志。因此,例如,当您这样做时:

$patient = Patient::with('intensiveTreatments')->get();

您实际上只急于加载治疗,而不是治疗日志。这就是为什么当您稍后访问每个治疗的治疗日志时,它们是未过滤的。

如果我需要更好地解释,请告诉我 - 我这里的术语并不完美。

您可以使用 JOIN:

public function intensiveTreatments()
{
    return $this->treatments()
        ->select('treatments.*')
        ->join('treatment_logs', 'treatments.id', 'treatment_logs.treatment_id')
        ->where('treatment_logs.status', 1)
        ->where('treatment_logs.id', function($query) {
            $query->select('id')
                ->from('treatment_logs')
                ->whereColumn('treatment_id', 'treatments.id')
                ->orderByDesc('id')
                ->limit(1);
        });
}

或整合到whereHas():

public function intensiveTreatments()
{
    return $this->treatments()->whereHas('treatment_logs', function ($query) {
        $query->where('status', 1)
            ->where('id', function ($query) {
                $query->select('id')
                    ->from('treatment_logs as latest')
                    ->whereColumn('latest.treatment_id', 'treatment_logs.treatment_id')
                    ->orderByDesc('id')
                    ->limit(1);
            });
    });
}