mysql删除行,保留每个user_id的最后5个

时间:2013-06-11 01:46:50

标签: mysql

我有一个mysql表(“c5_imgs”),其中包含“user_id”(varchar)和“date”(时间戳)列。此特定表中的数据量增长远远超过我最初的预期,现在我正在尝试删除除最近5个之外的每个user_id的所有记录。

对于给定的user_id,我可以获取要删除的行:

select *
FROM c5_imgs i
where 
    date < (
        select date 
        from c5_imgs i2 
        where i.user_id = i2.user_id 
        order by i2.date desc
        limit 4,1
    )
and user_id = 'xxx'

但是我在删除这些行时遇到了问题:

delete
FROM c5_imgs
where 
    date < (
        select date 
        from c5_imgs i2 
        where 'xxx' = i2.user_id 
        order by i2.date desc
        limit 4,1
    )
and user_id = 'xxx'

#1093 - You can't specify target table 'c5_imgs' for update in FROM clause

我希望为所有user_id制作一个通用查询,而不是一次一个...任何帮助将不胜感激,谢谢。

编辑:chetan的回答帮助我删除了一个user_id,但我正在为所有user_id寻找更通用的解决方案。

Edit2 :我最终使用的查询基于Christian的回答:

delete aa.* 
from c5_imgs aa,
(
select distinct c.user_id as user_id,
    (select x.date 
    from c5_imgs as x
    where x.user_id = c.user_id
    order by x.date desc
    limit 4,1) as date
from c5_imgs as c
) bb
where aa.user_id = bb.user_id and aa.date < bb.date

2 个答案:

答案 0 :(得分:1)

你可以使用join来做到这一点。例如

delete a.*
FROM c5_imgs a, (
        select date 
        from c5_imgs
        where 'xxx' = user_id 
        order by date desc
        limit 4,1
    ) b
where 
    a.date < b.date
and a.user_id = 'xxx';

我没有运行此查询,但它应该可以运行。必要时可以解决。

答案 1 :(得分:1)

您可以分三步完成:

First

create table aux
select distinct c.user_id as user_id,
    (select x.date 
    from c5_imgs as x
    where x.user_id = c.user_id
    order by x.date desc
    limit 4,1) as date
from c5_imgs as c;

第二

delete c5_imgs
from c5_imgs as c
inner join aux as a on a.user_id = c.user_id
where  c.date < a.date;

第三

drop table aux;

如果使用大表,可以在aux表的列上创建索引以加快删除操作。

CREATE INDEX aux_idx1 ON aux(user_id);
CREATE INDEX aux_idx2 ON aux(date);

请注意,如果您有一个可以获取不同用户ID的用户表,则可以简化并提高第一步的速度。

这并不能保证准确保留5张最近的图片。如果第5个和下一个位置的多个图像的日期完全相同,则无法按要求运行。