【问题标题】:In a Laravel Model's relationship how do I return a relationship using GROUP BY and MAX?在 Laravel 模型的关系中,如何使用 GROUP BY 和 MAX 返回关系?
【发布时间】:2018-08-06 12:53:26
【问题描述】:

我有一个项目,该项目可以有附件。项目和文档都是模型/表格。

简化示例文档表:

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

我想要一些简单的版本控制,这样如果用户想要他们可以“替换”文档,新的表格行复制除 ID 和版本之外的所有先前条目值。

我的问题是我想使用关系来提取所有最新文档。我目前在项目模型中使用这个怪物:

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

【问题讨论】:

  • 请使用您尝试过的groupBy() 发布查询。
  • @JonasStaudenmeir 完成了,并不是说我认为它有很大帮助!似乎无法弄清楚如何对行进行分组,然后选择具有最高/最大版本的行
  • 你试过$query->orderBy('version', 'desc')->groupBy('filename');
  • @rkj 解决这个错误:SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'app.documents.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
  • 你能在config/database.php 中添加'strict' => false 吗?然后尝试

标签: mysql laravel eloquent laravel-5.4


【解决方案1】:

我的建议是创建一个基于文档表的 MySQL 视图,该表始终只包含最新的文档文件,并简单地与该视图建立关系。所以:

第一步/创建视图:

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;

第二步/创建视图模型:

<?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 周围使用此功能。

【讨论】:

  • 这样的结果是查询从文​​档表中找到最大版本号,然后只返回具有该版本的文档。
  • @MikeK 那么在这种关系中,您究竟想用最大版本做什么?您要按它对文档进行排序吗?
  • 我想找到每个文件版本号最高的条目,然后返回这些结果。但是,在 DB 条目之间,只有文件版本和 ID 会发生变化(以及 created_at 等其他字段)。
  • @MikeK 我的建议是创建一个基于文档表的 MySQL 视图,该视图始终只包含最新的文档文件,并简单地与该视图建立关系。
  • @MikeK 我在这里编辑了我的答案。请检查它是否有效。
猜你喜欢
  • 2022-01-25
  • 2017-11-23
  • 2015-04-18
  • 2017-04-04
  • 2020-11-06
  • 2020-11-15
  • 2016-02-29
  • 2014-11-06
  • 2019-09-04
相关资源
最近更新 更多