【问题标题】:MySQL - Get previous row with a same identifierMySQL - 获取具有相同标识符的上一行
【发布时间】:2019-01-14 05:44:35
【问题描述】:

我在构建 MySQL 语句时需要帮助,我需要在同一个表中查找以前的行。

我的数据如下所示:

history_id(自动递增)、object_id(存在多次)、时间戳、...

示例:

1, 2593, 2018-08-07 09:37:21
2, 2593, 2018-08-07 09:52:54
3,   15, 2018-08-07 10:41:15
4, 2593, 2018-08-07 09:57:36

此数据的一些属性:

  • 自动增量越高,同一对象 ID 的时间戳就越晚
  • 一个object_id可能只有一行
  • object_id 和时间戳的组合始终是唯一的,不能重复

对于每一行,我需要找到具有相同 object_id 的最近一行。

我找到了这篇文章:https://dba.stackexchange.com/questions/24014/how-do-i-get-the-current-and-next-greater-value-in-one-select 并通过了示例,但我无法解决我的问题。

我只是测试了一下,就到了这一点:

SELECT
    i1.history_id,
    i1.object_id,
    i1.timestamp AS state_time,
    i2.timestamp AS previous_time
FROM
    history AS i1
    LEFT JOIN (
        select  timestamp as timestamp,history_id as history_id,object_id as object_id
        from        history
        group by object_id
        ) AS i2 on i2.object_id = i1.object_id and i2.history_id < i1.history_id 

现在我只需要剪切子查询,我只能为每一行获得最高的 history_id 值,但当我使用限制 1 时它不起作用,因为那样我只会得到一个值。

您对如何解决这个问题有任何想法吗?或者您可能有更好、更有效的技术?

性能很重要,因为我有 310 万行越来越高..

谢谢!

【问题讨论】:

标签: mysql join row identifier next


【解决方案1】:

最好的方向是使用window函数。简单的lag(timestamp) 将通过正确的 order by 子句完成这项工作。见这里:https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html#function_lag

但如果你需要的只是

剪切子查询,我只获得每行的最高历史 ID 值,但当我使用限制 1 时它不起作用

然后从

更改子查询
select  timestamp as timestamp,history_id as history_id,object_id as object_id
        from        history
        group by object_id

select  object_id as object_id, MAX(history_id) as history_id, MAX(timestamp) as timestamp
        from        history
        group by object_id

一般来说,您不应该选择比 GROUP BY 子句中更多的列,除非它们包含在聚合函数中。

【讨论】:

  • 我也考虑过(对不起,我应该提到这一点。)但是在子查询内部,最高值高于从外部查询比较的行之一。不知何故,我需要在子查询中做一些事情,比如:history_id
  • 使用lag 函数不需要子查询。你应该做SELECT history_id, object_id, timestamp as state_time, lag(timestamp) as prev_timefrom history WINDOW w AS (order by object_id, timestamp); 但是要小心,当object_id 改变时,你可能会从以前的object_id 得到时间戳。 (不确定MySQL如何处理这个)。然后你可以用case when lag(object_id) != object_id then NULL else lag(timestamp) end as prev_time替换lag(timestamp) as prev_time
猜你喜欢
  • 2022-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-27
  • 1970-01-01
  • 1970-01-01
  • 2020-08-22
  • 2012-08-23
相关资源
最近更新 更多