SQL:删除除每个用户的最后X条消息之外的旧消息

时间:2011-07-13 23:17:04

标签: mysql sql postgresql

我正在构建一个活动流,因此旧消息会从最终消失,永远不会再被看到。所以,我想定期删除旧邮件。但是,我不希望它看起来像用户没有活动,所以我想在每个流中留下至少X个帖子。

简化,我的“消息”表有一个“mid”(消息ID,主键),一个“uid”(用户ID),一个“创建”日期(UNIX时间戳)和一个“消息”。所以我想做的是做这样的事情:

DELETE FROM messages
WHERE created < ? AND mid NOT IN (
    SELECT mid FROM messages m GROUP BY uid HAVING mid > (
        SELECT mid FROM messages WHERE uid = m.uid ORDER BY mid LIMIT 1 OFFSET ?
    )
)

但是,当我单独在NOT IN()内尝试查询时,它不返回任何结果。此外,我认为它不适用于您要删除的同一个表中的SELECT

如果有必要,我可以使用2个查询,但我希望没有必要。

我试过四处搜索,除了最后一条记录之外,还有很多关于如何删除所有内容的结果,但我没有找到任何关于删除除最后N条记录以外的内容的结果。

2 个答案:

答案 0 :(得分:2)

请查看这个问题,找出“每组前n个”问题的[mysql]解决方案:

How to SELECT the newest four items per category?

一旦你有一组由“每组前n个”中的所有行组成(这就是你想要保留的)。您只需删除那些不在该集合中的行:

delete x
where x.mid not in ( select mid
                     -- where top n per group criteria
                   )

这是另一个查看同一问题的链接:

http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/

答案 1 :(得分:1)

这模拟了sql server窗口函数行号,它按日期对每条消息进行编号。然后只删除数字大于10的消息。您可能需要在l.created&gt; = r.created之间翻转相等。

delete from messages
where mid in 
    (select  l.mid from (  
    select l.mid,l.created, count(*) as num
    from messages as l
    left outer join messages as r
        on l.mid = r.mid
        and l.created >= r.created 
    group by l.mid, l.created) a 
    where a.num > 10    
   and l.created < ?);