在laravel模型的关系中,如何使用groupby和max返回关系?

f0brbegy  于 2021-06-23  发布在  Mysql
关注(0)|答案(1)|浏览(447)

我有一个项目,项目可以有附件。项目和文档都是模型/表。
简化示例文档表:

-----------------------------------
| ID  | filename        | version |
-----------------------------------
| 1   | list.docx       | 1       |
| 2   | list.docx       | 2       |
| 3   | file.xls        | 1       |
-----------------------------------

我想要一些简单的版本控制,这样如果用户想要,他们就可以“替换”文档,用新表行复制除id和version之外的所有以前的条目值。
我的问题是我想用一个关系来提取所有最新的文档。我目前正在项目模型中使用这个怪物:

public function latest_documents()
{
    return $this->hasMany(Document::class)
        ->where('version', \DB::raw('(SELECT max(d.version) from documents d where d.filename = documents.filename)'))
}

一定有更好的办法?我尝试在关系中使用groupby()和max(),但出现了错误。
编辑:在db::raw解决方案之前尝试了“laravel方法”:

public function documents()
{
    return $this->hasMany(Document::class)->groupBy('filename')->max('version');
}

错误:

Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation
fgw7neuy

fgw7neuy1#

我的建议是创建一个基于documents表的mysql视图,它总是只包含最新的文档文件,并简单地与该视图建立关系。所以:
步骤1/创建视图:

create view latest_documents as
  select filename,
         max(version)  as version,
         project_id    as project_id,
         any_value(id) as id
  from documents
  group by project_id, filename;

步骤2/创建视图模型:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class LatestDocument extends Model
{
    //
}

步骤3/将关系添加到项目模型:

public function latest_documents()
{
    return $this->hasMany(LatestDocument::class);
}

我测试过这个应该有用。
注意:我用过 any_value() 第一步,根据 only_full_group_by . 因此,如果您禁用此模式(我不建议),就不需要在 id .

相关问题