【问题标题】:Postgresql: select MAX value from two joined tablesPostgresql:从两个连接表中选择 MAX 值
【发布时间】:2014-11-19 13:09:57
【问题描述】:

我有两张桌子:

tbl_status:
  id
  status_code
  month_digest_id
  project_id

tbl_project
  id
  name

tbl_month_digest:
  id
  month_ts

我有一个项目。每个项目都有零个或多个月的状态(存储在 tbl_month_digest 中)。给定一个项目 ID 列表,我需要获取最新的状态对象。

我在执行此操作时遇到了问题。在 MySQL 中,我可以从 tbl_month_digesttbl_status 的连接中进行选择,并添加 having tbl_month_digest.month_ts = max(tbl_month_digest.month_ts)。 Postgres 坚持要我将 tbl_month_digest.month_ts 添加到 group by,这并没有达到预期的效果。

是否可以在 postgresql 的单个 SQL 查询中获取项目列表的最新状态?

示例数据和预期结果:

tbl_month_digest:
id   month_ts
1    2014-05-01
2    2014-06-01
3    2014-07-01

tbl_project:
id    name
90    'Foundation'
91    'Testing'
92    'Examination'

tbl_status:
id  project_id  month_digest_id  status_code
1   90          1                'on_track'
2   90          2                'on_track'
3   90          3                'late'
4   91          1                'late'
5   91          2                'unknown'
6   91          3                'unknown'
7   92          1                'late'
8   92          2                'late'
9   92          3                'on_track'

给定项目 ID 90 和 91,我想获得

project_id  latest_status
90          'late'
92          'on_track'

【问题讨论】:

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


    【解决方案1】:

    我不确定为什么 91 的最新状态会是 on_track。但是,您可以使用窗口函数做您想做的事情。

    我的猜测是您甚至不需要 month_digest 表,因为 id 通常会按时间顺序排列。

    select s.project_id, s.status as latest_status
    from (select s.*,
                 row_number() over (partition by project_id order by month_digest_id desc) as seqnum
          from tbl_status s
          where project_id in (90, 91)
         ) 
    where seqnnum = 1;
    

    你可以用join做基本相同的事情:

    select s.project_id, s.status as latest_status
    from (select s.*,
                 row_number() over (partition by project_id order by md.month_ts desc) as seqnum
          from tbl_status s join
               tbl_month_digest md
               on s.month_digest_id = md.id
          where project_id in (90, 91)
         ) 
    where seqnnum = 1;
    

    编辑:

    其实在Postgres中,你可以使用distinct on

          select distinct on(s.project_id) s.project_id, s.status as latest_status
          from tbl_status s join
               tbl_month_digest md
               on s.month_digest_id = md.id
          where s.project_id in (90, 91) and s.status <> 'unknown'
          order by s.project_id, md.month_ts desc;
    

    我不确定你想对未知状态做什么。这只是将它们过滤掉。

    【讨论】:

    • 对不起。我的意思是把'92'='on_track'。由于实际实现中的细节,我不能依赖month_digest的id作为month_ts的代理——我需要查看实际月份。
    猜你喜欢
    • 1970-01-01
    • 2013-04-02
    • 2015-05-08
    • 2016-08-02
    • 1970-01-01
    • 2017-10-31
    • 2019-10-22
    • 1970-01-01
    • 2015-09-10
    相关资源
    最近更新 更多