假设我有一个表“ transactions”,其中有“ acct_id”,“ trans_date”和“ trans_type”列,我想过滤该表,以便每个账户只有最后一笔交易。显然我可以做类似的事情
SELECT acct_id, max(trans_date) as trans_date FROM transactions GROUP BY acct_id;
但后来我失去了trans_type。然后,我可以使用日期和帐户ID的列表进行第二次SQL调用,并取回我的trans_type,但这感觉很笨拙,因为这意味着要么将数据来回发送到sql服务器,要么意味着创建一个临时表。
有没有一种方法可以通过单个查询做到这一点,希望有一个通用方法可以与mysql,postgres,sql-server和oracle一起使用。
这是每组最大n查询的示例。这个问题每周都会在StackOverflow上出现几次。除了其他人提供的子查询解决方案之外,这也是我的首选解决方案,该解决方案不使用子查询GROUP BY,或CTE:
GROUP BY
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;
换句话说,返回一行,使不存在其他具有相同acct_id或更大的行trans_date。
acct_id
trans_date
此解决方案假定该trans_date值对于给定帐户而言是唯一的,否则可能会发生联系,并且查询将返回所有绑定的行。但这对于其他人提供的所有解决方案也是正确的。
我更喜欢这种解决方案,因为我经常在MySQL上工作,而MySQL的优化GROUP BY效果不是很好。因此,通常证明这种外部联接解决方案具有更好的性能。