SQLite:如何使用复合键从单个表中选择“每个用户的最新记录”?
Posted
技术标签:
【中文标题】SQLite:如何使用复合键从单个表中选择“每个用户的最新记录”?【英文标题】:SQLite: How to SELECT "most recent record for each user" from single table with composite key? 【发布时间】:2016-02-05 21:59:50 【问题描述】:我不是数据库专家,我觉得我缺少一些核心 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 的理解缺少什么,以便理解您为我的问题提供的解决方案为何真正有效? (参考一篇真正解释实践背后理论的好文章就足够了。)我想知道为什么该解决方案实际上有效,而不仅仅是它有效。
非常感谢您的宝贵时间!
【问题讨论】:
【参考方案1】:你可以试试这个:
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 很可能只使用该索引,因为该索引包含查询中涉及的两个字段。索引比表本身小,因此扫描或查找速度更快。
【讨论】:
这完全是我想要的,你甚至击败了我my own answer。谢谢!【参考方案2】:好吧,用真正的“d'oh!”时尚,我刚问完这个问题,就找到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 中所说的“for each”。我想我现在明白了。
自我提醒:保持简单,愚蠢。 :)
【讨论】:
谢谢。对我来说也很有魅力。以上是关于SQLite:如何使用复合键从单个表中选择“每个用户的最新记录”?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Spring Boot 中使用复合主键从 MySql 中检索数据