获取与数据透视表中的语句匹配的最新记录作为构建器查询

发布于 2025-01-16 18:30:39 字数 2128 浏览 3 评论 0原文

我有以下表格:

users

| id | name  |
--------------
| 1  | user1 |
| 2  | user2 |
| 3  | user3 |
| 4  | user4 |
| 5  | user4 |

user_tasks

| id  | user_id | task    | created at         |
---------------------------------------------------
| 1   | 1       | read_book   | 2020-08-04 00:00:00 |
| 2   | 1       | send_mail   | 2020-08-05 00:00:00 |
| 3   | 2       | read_book   | 2020-08-04 00:00:00 |
| 4   | 2       | send_mail   | 2020-08-05 00:00:00 |
| 5   | 3       | read_book   | 2020-08-05 00:00:00 |

statuses

| id  | name
--------------
| 1   | todo
| 2   | doing
| 3   | reviewing
| 4   | done

数据透视表:

user_task_statuses

| id  | task_id | status_id    | created_at        |
---------------------------------------------------
| 1   | 1       | 1            | 2020-08-04 00:00:00 |
| 2   | 2       | 2            | 2020-08-05 00:00:00 |
| 3   | 2       | 4            | 2020-08-05 00:00:00 |
| 5   | 3       | 1            | 2020-08-04 00:00:00 |
| 6   | 4       | 2            | 2020-08-05 00:00:00 |
| 7   | 5       | 1            | 2020-08-05 00:00:00 |
| 7   | 5       | 2            | 2020-08-05 00:00:00 |

我正在尝试接收以下用户:任务的最新状态为正在执行。通过以下构建器查询,我获取了过去具有 doing 状态的所有任务,但我只想检索当前/最新状态为 doing 的行。在构建器查询中会是什么样子?

return $query->whereHas('userTasks', function (Builder $query) use ($statuses) {
    return $query->whereHas('userTasksStatuses', function (Builder $query) use ($statuses) {
        return $query->whereIn('status_id', $statuses);
    });
});

数据透视表:

public function userTasksStatuses()
{
    return $this->belongsToMany(Status::class, 'user_task_statuses')->withPivot('created_at');
}

我想我有类似的 SQL 工作,但这仅限于一项任务,我不确定如何将其转换为构建器查询。

SELECT 
    * 
FROM 
    user_task_statuses
WHERE task_id = 1
AND status_id = (SELECT MAX(status_id) FROM user_task_statuses WHERE task_id = 1);

I have the following tables:

users

| id | name  |
--------------
| 1  | user1 |
| 2  | user2 |
| 3  | user3 |
| 4  | user4 |
| 5  | user4 |

user_tasks

| id  | user_id | task    | created at         |
---------------------------------------------------
| 1   | 1       | read_book   | 2020-08-04 00:00:00 |
| 2   | 1       | send_mail   | 2020-08-05 00:00:00 |
| 3   | 2       | read_book   | 2020-08-04 00:00:00 |
| 4   | 2       | send_mail   | 2020-08-05 00:00:00 |
| 5   | 3       | read_book   | 2020-08-05 00:00:00 |

statuses

| id  | name
--------------
| 1   | todo
| 2   | doing
| 3   | reviewing
| 4   | done

pivot table:

user_task_statuses

| id  | task_id | status_id    | created_at        |
---------------------------------------------------
| 1   | 1       | 1            | 2020-08-04 00:00:00 |
| 2   | 2       | 2            | 2020-08-05 00:00:00 |
| 3   | 2       | 4            | 2020-08-05 00:00:00 |
| 5   | 3       | 1            | 2020-08-04 00:00:00 |
| 6   | 4       | 2            | 2020-08-05 00:00:00 |
| 7   | 5       | 1            | 2020-08-05 00:00:00 |
| 7   | 5       | 2            | 2020-08-05 00:00:00 |

I'm trying to receive the users that have tasks that have the doing as its latest status. With the following Builder query I get all tasks that have had a doing status in the past, but I only want to retrieve the rows which current/latest status are doing. How would that look like in a builder query?

return $query->whereHas('userTasks', function (Builder $query) use ($statuses) {
    return $query->whereHas('userTasksStatuses', function (Builder $query) use ($statuses) {
        return $query->whereIn('status_id', $statuses);
    });
});

Pivot table:

public function userTasksStatuses()
{
    return $this->belongsToMany(Status::class, 'user_task_statuses')->withPivot('created_at');
}

I think I have something similar working with SQL, but this is limited to one task and I'm not sure how to convert this into a builder query.

SELECT 
    * 
FROM 
    user_task_statuses
WHERE task_id = 1
AND status_id = (SELECT MAX(status_id) FROM user_task_statuses WHERE task_id = 1);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

娇纵 2025-01-23 18:30:39

您需要按您现在订购的同一字段进行排序,但按降序排列。举个例子,如果你有一个上传完成时的时间戳,称为 upload_time,你会这样做;

return $query->whereIn('status_id', $statuses)->orderBy('upload_time', 'DESC')->first();

You'll need to order by the same field you're ordering by now, but descending. As an example, if you have a time stamp when the upload was done called upload_time, you'd do something like this;

return $query->whereIn('status_id', $statuses)->orderBy('upload_time', 'DESC')->first();
演出会有结束 2025-01-23 18:30:39

设法像这样解决它:

return $query->whereHas('userTasks.userTasksStatuses', function (Builder $query) use ($statuses) {
    $query->whereRaw('user_task_statuses.id = (SELECT MAX(id) FROM user_task_statuses WHERE task_id = user_tasks.id)');
    $query->whereIn('status_id', $statuses);
});

Managed to resolve it like so:

return $query->whereHas('userTasks.userTasksStatuses', function (Builder $query) use ($statuses) {
    $query->whereRaw('user_task_statuses.id = (SELECT MAX(id) FROM user_task_statuses WHERE task_id = user_tasks.id)');
    $query->whereIn('status_id', $statuses);
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文