2011-07-26 36 views
2

我有結構像這樣的表:刪除行:無單件具有超過X個記錄

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工作。不是需要實時完成的事情。

回答

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,我有在查詢頂部2行進行測試。

所以我的查詢應該刪除每個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的行刪除了。這些是在每個member_id組具有秩> 2的行

+0

這不適合我。我在SELECT COUNT(*)FROM member_logins WHERE member_id = 1的表上測試,返回80+行,但運行查詢顯示0行受到影響。我甚至將DELETE更改爲SELECT,並返回0行。 – mellowsoon

+0

修復了查詢。現在工作 – 2011-07-26 13:49:13

0

僞碼 - 這很可能會去的存儲過程或程序邏輯:

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 

現在,插入新的成員登錄記錄。

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 

可以通過簡單的SELECT從member表被替換:

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

這將是一個夜間cron工作

否 - 解決問題的方法不正確 - 批量作業難以管理和測試,並且對於大多數面向互聯網的站點,不存在每日停機時間。這是更好地分散負載,並且僅運行代碼時,你需要,即當....

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

用戶登錄,這將是一個很多與索引更有效的對member_id

+0

他可能需要'ORDER BY date_created DESC',但我認爲這是最好的。簡單而高效。 –

+0

@ypercube - 是的 - 我有錯誤的方式排序 - 很好的發現。應該是DESC來保留最近的50個(即將修改答案),但是在沒有交錯插入ID的情況下(即,對於主 - 主複製),id將隨着date_created一起增加。 – symcbean