Удаление строк: ни один участник не имеет больше чем x записей - PullRequest
2 голосов
/ 26 июля 2011

У меня есть таблица, структурированная так:

CREAT TABLE `member_logins` (
    `id` bigint(10) unsigned not null auto_increment,
    `member_id` mediumint(8) unsigned not null,
    `date_created` datetime not null,
    PRIMARY KEY(`id`)
) ENGINE=InnoDB;

Я хочу сохранить только 50 логинов для каждого участника. Поэтому я ищу способ УДАЛИТЬ строки для каждого члена, любые строки после последних 50.

Редактировать: Я должен был упомянуть ... Это была бы ночная работа cron. Не то, что нужно делать в реальном времени.

Ответы [ 4 ]

2 голосов
/ 26 июля 2011
  DELETE FROM member_logins
  WHERE id in(
       SELECT ID
       FROM (SELECT 
               ID,member_id, 
               IF( @prev <> member_id, @rownum := 1, @rownum := @rownum+1 ) AS  rank, 
               @prev := member_id,date_created 
               FROM member_logins t 
               JOIN (SELECT @rownum := NULL, @prev := 0) AS r 
            ORDER BY t.member_id,t.date_created desc) as tmp
        where tmp.rank > 2)

Исправлен запрос. Проверено на примере данных, и это работает для меня.

Образец данных, загруженных для тестирования

id  member_id   date_created
1   1   2/26/2011 12:00:00 AM
2   1   5/26/2011 12:00:00 AM
3   1   4/26/2011 12:00:00 AM
4   2   5/26/2011 12:00:00 AM
5   2   3/26/2011 12:00:00 AM
6   2   4/26/2011 12:00:00 AM

Вместо 50 у меня в запросе есть две верхние строки для тестирования.

Таким образом, мой запрос должен удалить все строки, имеющие ранг> 2 в каждой группе member_id, где в строках упорядочено по date_created desc.

Вывод после выполнения запроса на удаление:

id  member_id   date_created
2   1   5/26/2011 12:00:00 AM
3   1   4/26/2011 12:00:00 AM
4   2   5/26/2011 12:00:00 AM
6   2   4/26/2011 12:00:00 AM

Вы можете видеть строки с ID 1 и 5, которые были удалены. Это строки с рангом> 2 в каждой группе member_id

1 голос
/ 26 июля 2011

Это будет ночная работа cron

Нет - не верный способ решения проблемы - пакетные задания сложно управлять и тестировать, а для большинства сайтов, подключенных к Интернету, ежедневных простоев нет. Намного лучше распределить нагрузку и запускать код только тогда, когда вам нужно, т.е. когда пользователь входит в систему ....

DELETE FROM member_logins
WHERE member_id=?
ORDER BY id DESC
LIMIT 50,10;

Что будет намного эффективнее с индексом member_id

0 голосов
/ 26 июля 2011
DELETE  m
FROM member_logins AS m
  JOIN ( SELECT DISTINCT member_id
         FROM member_logins
       ) AS md
    ON  md.member_id = m.member_id
    AND m.date_created <
        ( SELECT mx.date_created
          FROM ( SELECT *
                 FROM member_logins
               ) AS mx
          WHERE mx.member_id = md.member_id
          ORDER BY mx.date_created DESC
          LIMIT 1 OFFSET 49
        ) 

Подзапрос

  JOIN ( SELECT DISTINCT member_id
         FROM member_logins
       ) AS md
    ON  md.member_id = m.member_id

можно заменить простым SELECT из таблицы member:

  JOIN member AS md
    ON  md.member_id = m.member_id
0 голосов
/ 26 июля 2011

PsuedoCode - Скорее всего, это будет происходить в логике хранимых процедур или программ:

Set @MemberCount = Select Count(member_ID) from member_logins where member_id = @memberid

While (@MemberCount >= 50)
Begin
 Set @Id = Select Min(id) from member_logins where member_id = @memberid
 Delete from member_logins where id = @Id
 Set @MemberCount = @MemberCount - 1
End

Теперь вставьте новую регистрационную запись участника.

...