2011-07-13 86 views
3

我正在構建一個活動流,因此舊消息將不再出現,並且永遠不會再看到。所以,我想定期刪除舊信息。但是,我不希望它看起來像用戶沒有活動,所以我想在每個流中留下至少X個帖子。我的「消息」表具有「mid」(消息ID,主鍵),「uid」(用戶ID),「創建」日期(UNIX時間戳)和「消息」。因此,我要的是做這樣的事情:SQL:刪除每個用戶最近一次X消息以外的舊消息

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條記錄以外的所有內容。

+0

您的訂單是由消息ID確定的,還是僅由時間戳確定? –

+0

僅限於時間戳。 – IceCreamYou

+0

爲什麼你用mysql和postgresql標記這個?你在用哪個? –

回答

2

看這個問題了[MySQL的]解決「每組前N個」問題:

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/

+0

選擇此作爲給我一個更好的方式來構建我的問題的解決方案。 – IceCreamYou

1

這模擬的SQL Server窗口函數的行號是數字的每個消息按日期。然後只刪除數字大於10的消息。您可能需要翻轉l.created> = 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 < ?);