PostgreSQL中如何按用户查询表的最后一条记录
解决方法:查询每个用户的最后一条tracking记录
你原来的SQL有几个明显问题:
- 表名写错了:目标表是
activity-history-tracking,你写成了activity-historic-tracked - 字段名错误:你的表结构里是
username,但你用了user_id - 逻辑冗余:子查询已经按用户分组拿到了最新日期,外层没必要再做GROUP BY,而且这种写法也没法拿到完整的tracking记录
下面给你三种在PostgreSQL里可行的实现方案:
方案1:用DISTINCT ON(PostgreSQL专属,简洁高效)
PostgreSQL特有的DISTINCT ON语法可以快速实现需求:
SELECT DISTINCT ON (username) * FROM "activity-history-tracking" ORDER BY username, date DESC;
原理:DISTINCT ON (username)会保留每个username对应的第一条记录,配合ORDER BY username, date DESC,让每个用户的最新记录排在分组的最前面,从而被筛选出来。
方案2:用窗口函数ROW_NUMBER()(通用兼容)
如果需要兼容其他数据库,或者要处理更复杂的排序逻辑,窗口函数是更好的选择:
SELECT id, username, date, tracking FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY username ORDER BY date DESC) AS row_num FROM "activity-history-tracking" ) AS temp_table WHERE row_num = 1;
原理:内层查询通过PARTITION BY username按用户分组,ORDER BY date DESC让每组内最新的记录排第一,给每条记录标记行号;外层筛选行号为1的记录,就是每个用户的最新tracking记录。
方案3:用MAX(date)关联原表(传统关联写法)
先统计每个用户的最新日期,再关联原表拿到完整记录:
SELECT t.* FROM "activity-history-tracking" t INNER JOIN ( SELECT username, MAX(date) AS last_activity_date FROM "activity-history-tracking" GROUP BY username ) AS latest_dates ON t.username = latest_dates.username AND t.date = latest_dates.last_activity_date;
原理:子查询先算出每个用户的最新活动日期,再通过用户名和日期匹配原表,拿到对应的完整记录。注意:如果同一个用户在同一时间有多条记录,这个方法会返回所有符合的记录,前两种方法只会返回排序后的第一条。
内容的提问来源于stack exchange,提问作者Izlia
相关产品推荐
相关产品推荐

