我不是数据库专家,我觉得我缺少一些核心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的理解缺少什么,以便理解为什么您提供给我的问题的解决方案实际上有效? (参考一篇很好的文章,实际上解释了实践背后的理论就足够了。)我想知道为什么解决方案确实有效,而不仅仅是它。
非常感谢你的时间!
答案 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中。我想我现在就明白了。
自我注意:保持简单,愚蠢。 :)