删除行:没有单个成员具有超过x个记录

时间:2011-07-26 02:54:09

标签: mysql sql greatest-n-per-group sql-delete

我有一个像这样的结构表:

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 个答案:

答案 0 :(得分:2)

  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,我在查询前两行进行测试。

所以我的查询应删除所有排名为&gt;的行每个member_id组中的2,其中行由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的行。这些是具有等级&gt;的行。每个member_id组中有2个

答案 1 :(得分:1)

  

这将是一个夜间的cron工作

否 - 不是解决问题的正确方法 - 批量作业难以管理和测试,对于大多数面向互联网的站点而言,没有每日停机时间。分散负载要好得多,只在需要时运行代码,即用户登录时....

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

使用member_id

上的索引可以提高效率

答案 2 :(得分:0)

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

现在插入新会员登录记录。

答案 3 :(得分:0)

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
可以用member表中的简单SELECT替换

  JOIN member AS md
    ON  md.member_id = m.member_id