【问题标题】:MySQL - select rows under an ID, group by column value that has the latest timestampMySQL - 选择 ID 下的行,按具有最新时间戳的列值分组
【发布时间】:2017-03-25 19:36:57
【问题描述】:

表:

----------------------------------------------------
ID | field_name | field_value | timestamp
----------------------------------------------------
2  | postcode   | LS1         | 2016-11-09 16:45:15
2  | age        | 34          | 2016-11-09 16:45:22
2  | job        | Scientist   | 2016-11-09 16:45:27
2  | age        | 38          | 2016-11-09 16:46:40
7  | postcode   | LS5         | 2016-11-09 16:47:05
7  | age        | 24          | 2016-11-09 16:47:44    

不知道有没有人可以指点一下,根据上面的数据,我想通过ID 2查询,为每个唯一的field_name返回一行(如果同一个id下存在多行同field_name 然后只返回具有最新时间戳的行)。

我几乎通过对 field_name 进行分组来实现这一点,这将返回唯一行的列表,但不一定是最新的行。

SELECT * FROM fragment WHERE (id = :id) GROUP BY field_name

我真的很感激任何关于我应该在这里做什么的指针,以及我如何在这个查询中按照 MAX(timestamp) 的线来适应一些东西,

非常感谢!

【问题讨论】:

    标签: mysql sql database


    【解决方案1】:

    假设您首先需要为每个 ID 提供一组数据,即 FieldName 以及最大时间戳。 (生成该集合)作为内联视图(下面的 B)。然后,将此集合 (B) 连接回您的基本集合,允许内部连接消除不需要的行。

    SELECT A.ID, A.field_name, A.field_value, A.timestamp
    FROM Table A
    INNER JOIN (SELECT ID, field_name, MAX(timestamp) TS 
                FROM table 
                GROUP BY ID, field_name) B
     on A.ID = B.ID
    and A.field_name = B.field_name
    and A.timestamp = B.TS
    

    在 MySQL 之外,这可以使用窗口/分析函数来完成,因为您可以为每条记录分配一个行号并消除那些 > 1 之类的......

    SELECT B.* 
    FROM (SELECT A.ID
               , A.field_name
               , A.field_Vale
               , A.timestamp
               , Rownumber() over (Order by A.timestamp Desc) RN
          FROM Table A ) B
    WHERE B.RN = 1
    

    或使用带有限制或顶部的交叉应用。

    【讨论】:

    • 非常感谢这个例子,我将你的逻辑应用到我的查询中,并且在 B(集合)下我还添加了一个 WHERE 来传递我想要返回的 ID,非常感谢解释和附加示例,我当然只在这里使用 MySQL,但非常清楚,谢谢。
    【解决方案2】:

    最简单的方法:

      SELECT *
      FROM fragment fra1
      WHERE (id = :id)
        and timestamp = (select max(timestamp)
                         from fragment fra2
                         where fra2.id = fra1.id
                           and fra2.field_name = fra1.field_name)
      GROUP BY field_name
    

    【讨论】:

    • 您需要在内部选择中包含field_name
    • 为什么是外部分组(select * 上没有聚合)?否则,相关的子查询似乎会起作用。
    • 检查编辑:你不能把两个字段放在一个=比较
    • 谢谢!我已经尝试了两种方法,这似乎更容易理解,就基准测试/性能而言,这与@xQbert 建议的内部连接有很大区别吗?我会尝试做一些测试
    • @simonel 我会尝试两者,请务必评估两者的解释/执行计划!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-08
    • 1970-01-01
    • 1970-01-01
    • 2014-01-16
    • 2013-06-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多