【问题标题】:Postgresql extract last row for each idPostgresql 为每个 id 提取最后一行
【发布时间】:2015-03-21 01:11:35
【问题描述】:

假设我有下一个数据

  id    date          another_info
  1     2014-02-01         kjkj
  1     2014-03-11         ajskj
  1     2014-05-13         kgfd
  2     2014-02-01         SADA
  3     2014-02-01         sfdg
  3     2014-06-12         fdsA

我想为每个id提取最后的信息:

  id    date          another_info
  1     2014-05-13         kgfd
  2     2014-02-01         SADA
  3     2014-06-12         fdsA

我怎么能做到这一点?

【问题讨论】:

    标签: sql postgresql greatest-n-per-group


    【解决方案1】:

    我发现这是最快的解决方案:

     SELECT t1.*
       FROM yourTable t1
         LEFT JOIN yourTable t2 ON t2.tag_id = t1.tag_id AND t2.value_time > t1.value_time
      WHERE t2.tag_id IS NULL
    

    【讨论】:

      【解决方案2】:

      最有效的方法是使用 Postgres 的 distinct on 运算符

      select distinct on (id) id, date, another_info
      from the_table
      order by id, date desc;
      

      如果您想要一个跨数据库工作的解决方案(但效率较低),您可以使用窗口函数:

      select id, date, another_info
      from (
        select id, date, another_info, 
               row_number() over (partition by id order by date desc) as rn
        from the_table
      ) t
      where rn = 1
      order by id;
      

      使用窗口函数的解决方案在大多数情况下比使用子查询更快。

      【讨论】:

      • 点赞!它需要日期 desc 上的索引,但我总是假设索引可以在两个方向上搜索,日期上的升序默认主键索引应该适用于同一字段的降序,在我的情况下,我有复合键 (id, date)导致问题的复合键?
      • 根据the latest Postgres docs,索引确实在两个方向上都起作用除非它们用于多个列并且您在某些列上翻转方向但不是全部。所以date ASCdate DESC 上的索引都可以工作,但id ASC, date ASC 上的索引不会。您可以创建一个id ASC, date DESC 索引,或者将您的查询更改为ORDER BY id DESC, date DESC 以使其与id ASC, date ASC 索引一起使用。
      【解决方案3】:
      select * 
      from bar 
      where (id,date) in (select id,max(date) from bar group by id)
      

      在 PostgreSQL、MySQL 中测试

      【讨论】:

      • 如果单个 id 有多个具有相同日期的行,这将给出重复的结果
      【解决方案4】:

      按 id 分组并使用任何聚合函数来满足最后一条记录的条件。例如

      select  id, max(date), another_info
      from the_table
      group by id, another_info
      

      【讨论】:

      • 再次,这不会给出实际输出
      • 我在这里缺少什么?
      • 您正在根据 another_info 区分组,因此这不会仅按 id 分组。相反,如果您在 another_info 上使用聚合函数来获得正确的分组,那么聚合函数(比如 max())将不会返回具有 max(date) 的行的 another_info 值。事实上,这两个观察结果首先是这个问题的原因。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-01
      • 2017-07-22
      • 2021-01-23
      • 2023-02-06
      • 2021-09-27
      相关资源
      最近更新 更多