【问题标题】:Doctrine 2 - Retrieving the lastest record from history tableDoctrine 2 - 从历史表中检索最新记录
【发布时间】:2017-01-12 20:52:50
【问题描述】:

使用status_history 表将保存entries 中特定记录的状态修改日期和时间,我试图找到最简单的方法来获取当前状态,AKA,状态最近的日期。

例如考虑以下内容:status_history

+----+----------+------------+-----------+
| id | entry_id |   status   | timestamp |
+----+----------+------------+-----------+
|  1 |        1 | Processing | 15:05:09  |
|  2 |        1 | In Review  | 15:05:18  |
|  3 |        1 | Complete   | 15:05:26  |
+----+----------+------------+-----------+

当然,我们的条目:entries

+----+--------+
| id | title  |
+----+--------+
|  1 | Foobar |
+----+--------+

我如何使用 DQL 检索特定条目的最新状态(技术上是当前状态),无需维护 latest_status_id我的Entry 实体?

考虑调用$entry->getCurrentStatus() 将返回"Complete"。但是,如果我们对该条目有大量状态记录,则加载所有状态的第二次查询可能会导致性能下降。

注意:this article 中,他们使用额外列方法来描述它,使用并发锁定机制。我想避免这种方法,除非这是正确的方法,因为我们试图不让每个表都有双重关系(status_history.entry_identry.latest_history_id)。

【问题讨论】:

  • 如何获取$entry
  • 当然使用 DQL。但是,查询本身就是我想要弄清楚的,因为这个想法是它也带来了它的状态的最后一行。
  • 如果查询是您想要弄清楚的,我建议您将其添加到帖子中。可能会降低人们在帮助或朝着正确方向轻推的障碍
  • 谢谢。我编辑了问题。
  • - 您想在同一个查询中检索条目和 status_history 吗? - 您是否在第一个查询中检索多个条目? - 你想检索整个实体还是只检索字段?

标签: php mysql doctrine-orm doctrine


【解决方案1】:

对于单个条目,查询可能如下所示:

$query = $em->createQuery('SELECT e, s 
    FROM entries e 
    JOIN e.status_history s 
    WHERE e.entry_id = :entry_id
    ORDER BY s.timestamp DESC');
$query->setParameter('entry_id', $entry_id);
$entries = $query->getSingleResult();

在您的 getCurrentStatus() 方法中,您可以返回唯一分配的 status_history 对象。

对于所有条目,它都比较复杂,您必须使用带有GROUP BYMAX() 的子查询。这在本机 SQL 中是可行的,但我还没有弄清楚如何使用 DQL 来做到这一点。找到解决方案后,我会立即更新我的答案。

【讨论】:

    【解决方案2】:

    我认为在您的状态历史存储库中使用QueryBuilder 就足够了:

    $entry_id = 1;
    $queryBuilder = $this->createQueryBuilder()
        ->select('s')
        ->where('s.entry = :entry_id')
        ->orderBy('o.id', 'DESC')
        ->setParameter('entry_id', $entry_id)
    $query = $queryBuilder->getQuery();
    return $query->getSingleResult();
    

    您可以使用 id 假设 id 是“自动递增”并且 timestamp 是创建记录的自动时间戳。在这种情况下,最高 id 始终是最新插入,因此您甚至不需要使用 timestamp 列来查找该记录。

    否则,您必须向 timestamp 列添加索引并按该列排序:

    $entry_id = 1;
    $queryBuilder = $this->createQueryBuilder()
        ->select('s')
        ->where('s.entry = :entry_id')
        ->orderBy('o.timestamp', 'DESC')
        ->setParameter('entry_id', $entry_id)
    $query = $queryBuilder->getQuery();
    return $query->getSingleResult();
    

    您需要为 timestamp 列添加索引以提高性能

    【讨论】:

    • 你不应该按时间戳而不是 id 来订购吗?
    • 视情况而定。甚至可能没有必要。请阅读答案下的评论。
    猜你喜欢
    • 1970-01-01
    • 2017-10-20
    • 2011-05-18
    • 1970-01-01
    • 2015-10-08
    • 1970-01-01
    • 2023-04-05
    • 2013-07-13
    • 1970-01-01
    相关资源
    最近更新 更多