SQL: удалить старые сообщения, кроме последних X сообщений для каждого пользователя - PullRequest
3 голосов
/ 14 июля 2011

Я создаю поток активности, поэтому старые сообщения падают с конца и никогда не будут видны снова. Итак, я хотел бы регулярно удалять старые сообщения. Однако я не хочу, чтобы это выглядело так, как будто у пользователя нет активности, поэтому я хочу оставить минимум X сообщений в каждом потоке.

Упрощенно, моя таблица "messages" имеет "mid" (идентификатор сообщения, первичный ключ), "uid" (идентификатор пользователя), "дата создания" (метка времени UNIX) и "message". Так что я хочу сделать что-то вроде этого:

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 ]

2 голосов
/ 14 июля 2011

Посмотрите на этот вопрос, чтобы найти [mysql] решение проблемы «top n per group»:

Как ВЫБРАТЬ четыре последних элемента в категории?

Как только у вас есть набор, состоящий из всех строк в «top n per group» (это то, что вы хотите сохранить).Вам просто нужно удалить строки, не входящие в этот набор:

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 голос
/ 14 июля 2011

Имитирует номер строки оконной функции sql серверов, нумерует каждое сообщение по дате. Затем удаляются только сообщения с номером больше 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 < ?);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...