【问题标题】:CakePHP (sub)query to get youngest record of each groupCakePHP(子)查询以获取每个组的最年轻记录
【发布时间】:2013-11-11 14:12:21
【问题描述】:

在一个项目中,我管理的发票的状态在其整个生命周期中都会发生变化。状态更改保存在另一个数据库表中,类似于:

|id|invoice_id|user_id|old_status_id|new_status_id|change_date        |
-----------------------------------------------------------------------
| 1|         1|      1|            1|            3|2013-11-11 12:00:00|
| 2|         1|      2|            3|            5|2013-11-11 12:30:00|
| 3|         2|      3|            1|            2|2013-11-10 08:00:00|
| 4|         1|      1|            5|            6|2013-11-11 13:10:00|
| 5|         2|      2|            2|            5|2013-11-10 09:00:00|

对于每张发票,我想检索最后一次状态更改。因此,结果应该包含 id 为 4 和 5 的记录。

|id|invoice_id|user_id|old_status_id|new_status_id|change_date        |
-----------------------------------------------------------------------
| 4|         1|      1|            5|            6|2013-11-11 13:10:00|
| 5|         2|      2|            2|            5|2013-11-10 09:00:00|

如果我按 invoice_id 分组并使用 max(change_date),我将检索最年轻的日期,但其他字段的字段值不会取自组中包含最年轻日期的记录。

这对我来说是第一个挑战。

挑战#2 是尽可能使用 CakePHP 的方法实现查询。

挑战#3 是将结果过滤到属于当前用户的那些记录。所以如果当前用户的id为1,结果是

|id|invoice_id|user_id|old_status_id|new_status_id|change_date        |
-----------------------------------------------------------------------
| 4|         1|      1|            5|            6|2013-11-11 13:10:00|

如果他或她的用户 id 为 2,则结果为

|id|invoice_id|user_id|old_status_id|new_status_id|change_date        |
-----------------------------------------------------------------------
| 5|         2|      2|            2|            5|2013-11-10 09:00:00|

对于 id 为 3 的用户,结果将为空。

换句话说,我确实想要查找用户所做的所有最新更改,无论他是否是最后一个进行更改的用户。相反,我想查找所有发票更改,其中该用户是迄今为止进行更改的用户。动机是我想让用户撤消他的更改,这只有在他之后没有其他用户执行另一个更改的情况下才有可能。

【问题讨论】:

    标签: mysql cakephp-2.3


    【解决方案1】:

    如果有人需要答案

    专注于:

    我想查找到目前为止该用户是最后一个进行更改的用户的所有发票更改

    将 SQL 编写为

    SELECT foo.*
    FROM foo
    LEFT JOIN foo AS after_foo
      ON foo.invoice_id = after_foo.invoice_id
        AND foo.change_date < after_foo.change_date
    WHERE after_foo.id IS NULL
      AND foo.user_id = 1;
    

    使用 Cakephp 的 find 中的 JOIN 子句实现。


    建议算法的 SQL 类似于:

    SELECT foo.*
    FROM foo
    JOIN (SELECT invoice_id, MAX(change_date) AS most_recent
          FROM foo
          GROUP BY invoice_id) AS recently
      ON recently.invoice_id = foo.invoice_id
        AND recently.most_recent = foo.change_date
    WHERE foo.user_id = 1;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-09
      • 2021-01-10
      • 1970-01-01
      • 1970-01-01
      • 2020-08-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多