php MySQL抓取一组数据的最后一行,但特定于列值

vsdwdz23  于 2023-08-02  发布在  PHP
关注(0)|答案(1)|浏览(87)

我们正在使用Laravel开发一个系统,这意味着我们正在使用Laravel ORM。我们有一个类似这样的表:

table: approvals
+----+-------------------------+--------+----------+----------+------+----------+
| id |        app_model        | app_id | group_id | revision | year |  status  |
+----+-------------------------+--------+----------+----------+------+----------+
|  1 | App\Models\AApplication |      4 |      500 | (NULL)   | 2021 | APPROVED |
|  2 | App\Models\AApplication |     95 |      501 | (NULL)   | 2022 | APPROVED |
|  3 | App\Models\BApplication |     22 |       90 | 1        | 2019 | APPROVED |
|  4 | App\Models\BApplication |     37 |       90 | 2        | 2020 | APPROVED |
|  5 | App\Models\AApplication |    125 |      501 | 1        | 2023 | APPROVED |
|  6 | App\Models\BApplication |     89 |       90 | 3        | 2024 | DRAFT    |
+----+-------------------------+--------+----------+----------+------+----------+

字符串
我们使用Laravel的morphTo()关系获取关系表数据:

public function app() {
    return $this->morphTo(__FUNCTION__, 'app_model', 'app_id');
}


我试图呈现一些数据,以便提供有关此表中数据维度的一些上下文。我们在此approvals表中保留了不同应用程序表的批准。单个机构可以根据每次申请获得修改批准多次。批准最初可以是“草案”,之后可以是“批准”。

我们需要获取组(group_id)中状态为“已批准”的最后一个修订行。

Approvals UI Grid
+-------+----------+--------+
| GROUP | REVISION | ACTION |
+-------+----------+--------+
|   500 |        - | [view] |
|   501 |        1 | [view] |
|    90 |     👉 2 | [view] |
+-------+----------+--------+


我们在Laravel ORM中做了以下MySQL查询来实现:

// $userId = get current user id;

$query = DB::table('approvals')
    ->with(['app'])
    ->whereNotIn('id', function ($query) {
        $query->from('approvals as t1')
            ->crossJoin('approvals as t2')
            ->whereColumn('t1.id', '<', 't2.id')
            ->whereColumn('t1.group_id', '=', 't2.group_id')
            ->whereColumn('t1.app_model', '=', 't2.app_model')
            ->select('t1.id');
    });

// Only show approvals of _that_ particular user.
$query = $query->whereRelation('app', 'created_by', '=', $userId);

$query = $query->orderBy('approvals.id', 'DESC');

$query = $query->where('approvals.status', 'APPROVED'); // <-------- 🟥 ISSUE IS HERE

return $query;


如果我们从查询中注解掉'APPROVED'条件,我们 * 可以 * 获得每个组的最后一行**。问题是,group_id 90的最后一行不是'APPROVED',但这不是我们想要的网格。

我们需要组的最后一行,但如果批准,否则应该是前一行-最后一行。

如何在MySQL中实现这一点?

n8ghc7c1

n8ghc7c11#

您希望获得每个group_id的最新APPROVED行。对于每个group_id,您希望找到具有最大值id的行,其中状态为APPROVED

如果是这样的话,我会这样做

$query = DB::table('approvals')
    ->with(['app'])
    ->whereNotIn('id', function ($query) {
        $query->from('approvals as t1')
            ->join('approvals as t2', function ($join) {
                $join->on('t1.group_id', '=', 't2.group_id')
                     ->on('t1.app_model', '=', 't2.app_model')
                     ->on('t1.id', '<', 't2.id')
                     ->where('t2.status', 'APPROVED');
            })
            ->select('t1.id');
    });

// Only show approvals of _that_ particular user.
$query = $query->whereRelation('app', 'created_by', '=', $userId);

$query = $query->orderBy('approvals.id', 'DESC');

$query = $query->where('approvals.status', 'APPROVED');

return $query;

字符串

编辑:说明

子查询通常返回所有id,其中有一行具有相同的group_idapp_model,以及更大的id,最后是Approvedstatus。这基本上消除了每个组中除了最新的APPROVED行之外的所有行。然后,外部查询选择这些最新的APPROVED行。

相关问题