【问题标题】:Search last known update for each object in SQL在 SQL 中搜索每个对象的最后一次已知更新
【发布时间】:2020-07-25 11:36:57
【问题描述】:

我有一个 2 表:一个存储对象 (Object) 和其他存储对象 (ObjectStateUpdate) 的状态更新(例如:NOT_DONE、BEING_MANUFACTURED、DONE): database diagram

每次对象状态更改时,都会在 ObjectStateUpdate 表中添加一行,其中包含新状态和状态更改日期。

在我的应用程序中,我有一个用例,我想检索处于特定状态的所有对象(假设所有正在制造的对象)。

这是通过一个复杂的 SQL 请求完成的,该请求根据更新日期获取每个对象的最后一个已知更新,如果同时发生两个更新,我使用更新的 id 来查找最后一个(每个对象至少有一次状态更新):

SELECT * 
FROM ObjectStateUpdate 
WHERE id =
(
    SELECT MAX(id) 
    FROM ObjectStateUpdate 
    INNER JOIN (
        SELECT objectId, MAX(date) AS max_date 
        FROM trade_manager_app_orderupdate GROUP BY objectId
    ) as Latest 
    ON ObjectStateUpdate.objectId = Latest.objectId 
    AND ObjectStateUpdate.date = Latest.max_date 
    GROUP BY ObjectStateUpdate.objectId
)

我正在考虑在对象表中添加一个外键列"lastUpdateId" 来存储对象的最后一次更新的 id(每次我有一个新的更新我都会将它的 id 存储为对象)。

这可以通过将其替换为更高效的 SQL 请求来避免执行大 SQL 请求,但我担心如果由于某种原因“lastUpdateId”不是最新的,它会在数据库模型中增加不一致ObjectStateUpdate 表的数据。

那么我应该将此列添加到对象表中以提高性能还是应该保持这种状态以避免不一致?

【问题讨论】:

    标签: sql database sqlite date greatest-n-per-group


    【解决方案1】:

    如果我没听错的话,您可以使用row_number() 大大简化您现有的查询(如果您的 SQLite 版本支持它们);

    select *
    from (
        select u.*, row_number() over(partition by objectId order by date desc, id desc) rn 
        from ObjectStateUpdate u
    ) t
    where rn = 1 and state = 'BEING_MANUFACTURED'
    

    您可以使用相关子查询获得相同的结果:

    您可以使用相关子查询获得相同的结果:

    select u.*
    from ObjectStateUpdate u
    where 
        id = (
            select u1.id
            from ObjectStateUpdate u1
            where u1.objectId = u.objectId
            order by date desc, id desc
            limit 1
        )
        and state = 'BEING_MANUFACTURED'
    

    为了提高性能,您需要在(objectId, date, id) 上建立索引。

    【讨论】:

      猜你喜欢
      • 2014-02-22
      • 2013-12-13
      • 1970-01-01
      • 1970-01-01
      • 2019-02-08
      • 1970-01-01
      • 2011-08-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多