SQLite:如何选择"每个用户的最新记录"来自带有复合键的单个表?

时间:2015-11-05 06:50:20

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

我不是数据库专家,我觉得我缺少一些核心SQL知识来解决这个问题。以下是我可以解释的情况。

上下文

我有一个SQLite数据库表,其中包含带时间戳的用户事件记录。可以通过时间戳和用户ID的组合(即,事件发生的时间和事件的参与者)唯一地识别记录。我知道这种情况被称为复合主键。"该表看起来像这样(当然删除了一堆其他列):

sqlite> select Last_Updated,User_ID from records limit 4;

Last_Updated   User_ID
-------------  --------
1434003858430  1   
1433882146115  3   
1433882837088  3   
1433964103500  2   

问题:我如何SELECT结果集仅包含每个用户的最新记录?

鉴于上面的例子,我想要回来的是一张如下表:

Last_Updated   User_ID
-------------  --------
1434003858430  1   
1433882837088  3   
1433964103500  2   

(请注意,结果集仅包含用户3的最新记录。)

实际上,我在这张表中有大约250万行。

奖金:我一直在阅读有关JOIN,重复数据删除程序以及更多内容的答案,而且我一直在谷歌搜索教程/文章,希望我会找到我失踪的东西。我有广泛的编程背景,所以我可以在程序代码中对这个数据集进行重复数据删除,就像我之前已经完成了一百次,但我已经厌倦了编写脚本来做我认为应该在SQL中可能做到的事情。那是什么,对吧?

那么,从概念上讲,我对SQL的理解缺少什么,以便理解为什么您提供给我的问题的解决方案实际上有效? (参考一篇很好的文章,实际上解释了实践背后的理论就足够了。)我想知道为什么解决方案确实有效,而不仅仅是它。

非常感谢你的时间!

2 个答案:

答案 0 :(得分:3)

你可以试试这个:

select user_id, max(last_updated) as latest
from records
group by user_id

这应该为您提供每位用户的最新记录。我假设你有一个关于user_id和last_updated组合的索引。

在上面的查询中,一般来说 - 我们要求数据库对user_id记录进行分组。如果user_id 1有超过1条记录,则它们将全部组合在一起。从该记录集中,将选择最大last_updated用于输出。然后寻找下一组,并在那里应用相同的操作。

如果你有一个复合索引,sqlite可能只会使用索引,因为索引包含查询中寻址的两个字段。索引小于表本身,因此扫描或搜索更快。

答案 1 :(得分:1)

嗯,真的" d'哦!"时尚,在我问这个问题之后,我找到the answer

就我而言,答案是:

SELECT MAX(Last_Updated),User_ID FROM records GROUP BY User_ID

我认为我需要使用JOIN和东西,这使得它变得比它更复杂。应用像MAX()之类的聚合函数只需选择那些内容与函数结果匹配的行。这意味着这句话......

SELECT MAX(Last_Updated),User_ID FROM records

...因此会返回一个只包含1行的结果集,即最近的事件。

但是,通过添加GROUP BY子句,结果集包含每个"组的行"结果,即每个用户。我的程序员大脑不明白GROUP BY是我们怎么说"对于每个"在SQL中。我想我现在就明白了。

自我注意:保持简单,愚蠢。 :)