SQL查询问题:按RelationId去重获取用户最近3条有权限操作记录
解决SQL查询中RelationId重复的问题
我来帮你搞定这个问题——你的核心需求是拿到用户有权限、按RelationId去重后的最近3条操作记录,但原SQL里的DISTINCT没起到预期的去重作用,因为它是基于整个Action行的所有字段来判断唯一性的,而每条Action记录的id是唯一的,所以即使RelationId相同,不同的id会被当成不同记录保留下来。
解决方案思路
要实现按RelationId去重(取每个RelationId下最新的操作记录),再关联权限验证,最后分页取前3条,我们可以用窗口函数来精准控制去重逻辑:
- 先对
Action表按RelationId分组,每组内按TimeStamp倒序排序,标记出每组的最新记录; - 过滤出仅包含每组最新记录的数据集;
- 将这个数据集与
Permission表关联,验证用户权限; - 最后按时间倒序,用你要求的
OFFSET/FETCH语法取前3条。
修正后的SQL语句
SELECT a_filtered.*, p.RelationId FROM ( SELECT a.*, -- 按RelationId分组,每组内按时间倒序,最新记录标记为1 ROW_NUMBER() OVER(PARTITION BY a.RelationId ORDER BY a.TimeStamp DESC) AS rn FROM [Action] [a] WHERE a.ActionType = 'Clicked' AND a.RelationType = 'Direct' AND a.UserId = 5 AND a.Deleted = 0 ) AS a_filtered INNER JOIN [Permission] p ON p.RelationId = a_filtered.RelationId AND p.RelationType = a_filtered.RelationType AND p.UserId = a_filtered.UserId AND p.Deleted = 0 -- 只保留每个RelationId下的最新操作记录 WHERE a_filtered.rn = 1 -- 按时间倒序,取最近3条 ORDER BY a_filtered.TimeStamp DESC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY;
逻辑说明
- 子查询
a_filtered中,ROW_NUMBER() OVER(PARTITION BY a.RelationId ORDER BY a.TimeStamp DESC)会给每个RelationId分组内的记录按时间从新到旧编号,最新的那条记录编号为1; - 过滤
rn = 1就完成了按RelationId去重的核心需求,确保每个RelationId只保留最新的操作记录; - 与
Permission表的关联条件完全保留了你原SQL中的校验逻辑,确保用户仍具备对应权限; - 最后用
OFFSET/FETCH实现分页,精准获取最近3条符合要求的记录。
内容的提问来源于stack exchange,提问作者LittleMygler
相关产品推荐
相关产品推荐

