【问题标题】:mysql delete rows keeping the last 5 for the each user_idmysql删除保留每个user_id最后5行的行
【发布时间】:2013-06-11 11:08:19
【问题描述】:

我有一个 mysql 表(“c5_imgs”),其中包含“user_id”(varchar)和“date”(时间戳)列。这个特定表中的数据量增长得比我最初预期的要多得多,现在我正在尝试删除每个 user_id 的所有记录,除了最近的 5 条记录。

对于给定的 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

【问题讨论】:

    标签: mysql


    【解决方案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 和下一个位置的多个图像的日期完全相同,则这将无法按要求工作。

    【讨论】:

    • 不,那是行不通的,至少不能同时对所有的 user_ids 。您的第一个表应该包含所有 user_id 以及每个用户 ID 的第 5 个结果,或者前 5 个。
    • 编辑了我的答案。看看这对你有没有帮助。
    • 谢谢,做到了。我最终只使用了删除,而不是创建中间表。我将编辑我的帖子以显示我使用的查询。
    【解决方案2】:

    您可以使用连接来做到这一点。例如

    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';
    

    我没有运行这个查询,但它应该可以工作。如有必要,请解决。

    【讨论】:

    • 谢谢,这解决了我的部分问题:),但我需要一个更通用的查询来为所有 user_id 做同样的事情
    猜你喜欢
    • 1970-01-01
    • 2019-07-17
    • 2014-04-11
    • 2018-10-14
    • 2021-12-28
    • 2014-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多