【问题标题】:Join with a second table containing multiple records, take the latest加入包含多条记录的第二个表,取最新的
【发布时间】:2017-08-17 05:25:37
【问题描述】:

我有两张桌子:

person_id | name
1            name1
2            name2
3            name3

还有第二张桌子:

person_id | date     | balance
1           2016-03     1200                    ---- \
1           2016-04     700                     ----  > same person
1           2016-05     400                     ---- /
3           2016-05     4000

考虑到 person_id 1 在第二张表上有三条记录,我怎样才能通过获取最新记录来加入第一条记录? (即:余额400,对应日期:2016-05)。

例如:查询输出:

person_id | name    | balance
1           name1     400
2           name2     ---
3           name3     4000

如果可能的话,更喜欢简单而不是解决方案的复杂性

【问题讨论】:

  • 你使用什么数据库引擎?
  • AWS Redshift 是一种具有较少功能的 postregres(如果可能,查询应该与 mysql 兼容)
  • 我删除了不兼容的数据库标签。请标记您真正使用的数据库。

标签: sql group-by left-join greatest-n-per-group amazon-redshift


【解决方案1】:

适用于所有数据库引擎的查询是

select t1.name, t2.person_id, t2.balance
from table1 t1
join table2 t2 on t1.person_id = t2.person_id
join
(
    select person_id, max(date) as mdate
    from table2
    group by person_id
) t3 on t2.person_id = t3.person_id and t2.date = t3.mdate

【讨论】:

  • 这是否考虑了在第二张表中找不到记录的情况(例如)?还是我必须用左连接替换您的连接?
  • 如果你总是想要person_id,你必须使用左连接
  • 不,因为当您分组时,您只能选择分组或聚合的列(例如 max()、min()、...)
  • @jurgen d:rigerta提供的答案只有1个加入,你这个他是正确的吗?
  • 不,因为 TOP 1/LIMIT 1 子查询只返回一条记录
【解决方案2】:

在任何支持 ANSI 标准窗口函数(其中大多数)的数据库中执行此操作的最佳方法是:

select t1.*, t2.balance
from table1 t1 left join
     (select t2.*,
             row_number() over (partition by person_id order by date desc) as seqnum
      from table2 t2
     ) t2
     on t1.person_id = t2.person_id and seqnum = 1;

【讨论】:

  • 有趣的是只有一个连接的使用,无论如何你认为像这样docs.aws.amazon.com/redshift/latest/dg/…这样使用windows的first_value会有点简化吗?
  • @gio 。 . .唉,first_value() 是窗口函数,不是聚合函数,所以不会减少行数。还是需要子查询和过滤,所以答案是等价的。
  • 好的,谢谢+1!无论如何,我将这个问题标记为每个组最大的问题,因为我认为基本上是同一件事。可悲的是,关于这个问题有很多问题,当在数据库中实现一个简单的 FIRST() 或 LAST() 函数可以解决所有问题时
猜你喜欢
  • 2014-03-03
  • 2018-07-11
  • 2012-07-03
  • 1970-01-01
  • 2013-06-15
  • 2012-08-07
  • 2020-11-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多