如何为每个帐户的最后一笔交易进行SQL查询?

Ste*_*ble 13 sql greatest-n-per-group

假设我有一个表"事务",其中包含"acct_id""trans_date"和"trans_type"列,我想过滤此表,以便我只拥有每个帐户的最后一笔交易.显然我可以做点什么

SELECT acct_id, max(trans_date) as trans_date  
FROM transactions GROUP BY acct_id;
Run Code Online (Sandbox Code Playgroud)

但后来我失去了我的trans_type.然后,我可以使用我的日期列表和帐户ID进行第二次SQL调用,然后返回我的trans_type,但这感觉很麻烦,因为它意味着要么来回发送数据到sql server,要么就是创建一个临时表.

有没有办法用一个查询来做到这一点,希望是一个可以与mysql,postgres,sql-server和oracle一起使用的泛型方法.

Bil*_*win 24

这是每组最大n查询的示例.这个问题每周在StackOverflow上出现几次.除了其他人提供的子查询解决方案之外,这里是我首选的解决方案,它不使用子查询GROUP BY,或CTE:

SELECT t1.*
FROM transactions t1
LEFT OUTER JOIN transactions t2
  ON (t1.acct_id = t2.acct_id AND t1.trans_date < t2.trans_date)
WHERE t2.acct_id IS NULL;
Run Code Online (Sandbox Code Playgroud)

换句话说,返回一行,使得不存在具有相同acct_id和更大的其他行trans_date.

此解决方案假定trans_date对于给定帐户是唯一的,否则可能会发生关联,并且查询将返回所有绑定的行.但对于其他人提供的所有解决方案也是如此.

我更喜欢这个解决方案,因为我经常使用MySQL,它不能GROUP BY很好地优化.因此,这种外部连接解决方​​案通常被证明对性能更好.


Dav*_*vid 11

这适用于SQL Server ...

SELECT acct_id, trans_date, trans_type
FROM transactions a
WHERE trans_date = (
   SELECT MAX( trans_date )
   FROM transactions b
   WHERE a.acct_id = b.acct_id
)
Run Code Online (Sandbox Code Playgroud)

  • 这是我最喜欢的.你也可以将你的where子句设置为"NOT EXISTS(SELECT NULL FROM transaction z where a aacct_id = z.acct_id AND z.trans_date> a.trans_date)" (2认同)