Mysql 优化sql查询以删除行

Mysql 优化sql查询以删除行,mysql,sql,database,activerecord,Mysql,Sql,Database,Activerecord,我有一张桌子,看起来有点像这样:- A B C D 1 2 0 2012-10-05 18:37:00 1 3 0 2012-10-05 20:37:00 1 4 1 2012-04-07 18:37:00 2 1 1 2012-10-05 18:12:40 2 2 0

我有一张桌子,看起来有点像这样:-

A      B        C         D 
1      2        0         2012-10-05 18:37:00
1      3        0         2012-10-05 20:37:00
1      4        1         2012-04-07 18:37:00
2      1        1         2012-10-05 18:12:40
2      2        0         2012-10-04 18:37:00
2      3        0         2011-10-05 12:37:00
ColA和ColB唯一标识一行。但是,它不是主键。ColC可以是0或1。ColD是一个日期时间字段。 我只需要保留表中colC为0的10行(或更少)和colC为1的10行(或更少),最大总行数为20。这10行(每行)是最近的行,即最近的10行(基于colD值),其colC值为0。类似地,保留的(最多)10行的ColC值为1,应该是前10行的ColC值为1

目前,为了实现这一点,我正在触发4个查询。我对colC值分别为0和1进行一次查询,以获得第11行(或更少)的时间戳。然后,对于获得的每个值,我触发另一个查询以删除所有“旧”行

我可以通过一个查询来实现这一点吗?如果不是,什么是最理想的解决方案


PS:-我正在应用程序中使用活动记录,因此必须相应地修改查询。

这应该适用于您:

DELETE
  ex
FROM
  ex
INNER JOIN
(
  SELECT
    C, MIN(D) D
  FROM
  (
    (
      SELECT
        C, D
      FROM
        ex
      WHERE
        C = 0
      ORDER BY
        D DESC
      LIMIT 10
    ) UNION (
      SELECT
        C, D
      FROM
        ex
      WHERE
        C = 1
      ORDER BY
        D DESC
      LIMIT 10
    )
  ) d1
  GROUP BY
    C
  ORDER BY
    C
) d2 ON d2.C = ex.C
WHERE
  ex.D < d2.D
返回:

C   cnt MIN(D)                  MAX(D)
0   10  10/5/2012 2:14:53 AM    10/5/2012 7:21:23 PM
1   10  10/2/2012 1:41:21 PM    10/5/2012 2:57:34 PM
有关工作示例,请参见

请注意,如果要删除超过50%的数据,您可能会发现最好
选择要保留在新表中的记录,然后
将该表重命名为现有表

下面是一个例子:

DROP TABLE IF EXISTS ex_old;
DROP TABLE IF EXISTS ex_new;
CREATE TABLE ex_new LIKE ex;

INSERT INTO
    ex_new
SELECT
    ex.*
FROM
    ex
INNER JOIN
(
  SELECT
    C, MIN(D) D
  FROM
  (
    (
      SELECT
        C, D
      FROM
        ex
      WHERE
        C = 0
      ORDER BY
        D DESC
      LIMIT 10
    ) UNION (
      SELECT
        C, D
      FROM
        ex
      WHERE
        C = 1
      ORDER BY
        D DESC
      LIMIT 10
    )
  ) d1
  GROUP BY
    C
  ORDER BY
    C
) d2 ON d2.C = ex.C
WHERE
  ex.D >= d2.D;

RENAME TABLE ex TO ex_old, ex_new TO ex;

这应该适合您:

DELETE
  ex
FROM
  ex
INNER JOIN
(
  SELECT
    C, MIN(D) D
  FROM
  (
    (
      SELECT
        C, D
      FROM
        ex
      WHERE
        C = 0
      ORDER BY
        D DESC
      LIMIT 10
    ) UNION (
      SELECT
        C, D
      FROM
        ex
      WHERE
        C = 1
      ORDER BY
        D DESC
      LIMIT 10
    )
  ) d1
  GROUP BY
    C
  ORDER BY
    C
) d2 ON d2.C = ex.C
WHERE
  ex.D < d2.D
返回:

C   cnt MIN(D)                  MAX(D)
0   10  10/5/2012 2:14:53 AM    10/5/2012 7:21:23 PM
1   10  10/2/2012 1:41:21 PM    10/5/2012 2:57:34 PM
有关工作示例,请参见

请注意,如果要删除超过50%的数据,您可能会发现最好
选择要保留在新表中的记录,然后
将该表重命名为现有表

下面是一个例子:

DROP TABLE IF EXISTS ex_old;
DROP TABLE IF EXISTS ex_new;
CREATE TABLE ex_new LIKE ex;

INSERT INTO
    ex_new
SELECT
    ex.*
FROM
    ex
INNER JOIN
(
  SELECT
    C, MIN(D) D
  FROM
  (
    (
      SELECT
        C, D
      FROM
        ex
      WHERE
        C = 0
      ORDER BY
        D DESC
      LIMIT 10
    ) UNION (
      SELECT
        C, D
      FROM
        ex
      WHERE
        C = 1
      ORDER BY
        D DESC
      LIMIT 10
    )
  ) d1
  GROUP BY
    C
  ORDER BY
    C
) d2 ON d2.C = ex.C
WHERE
  ex.D >= d2.D;

RENAME TABLE ex TO ex_old, ex_new TO ex;
这将起作用(请参阅):

这将创建要保留的20个值的列表,并删除其余值

如果性能是一个问题,我建议您将这20行放在一个单独的表中,截断原始表,然后将其插入。

这将起作用(请参阅):

这将创建要保留的20个值的列表,并删除其余值



如果性能是一个问题,我建议您将这20行放在一个单独的表中,截断原始表,然后将它们插入。

您对它做了什么?您是否有无效查询?我试图使用groupby命令在一个查询中获取时间戳的两个值,然后在另一个查询中删除行。请显示该代码,以便我们可以提供更多帮助。@DarshanThanki问题是,代码还不存在。您对此做了什么?您有一个不工作的查询吗?我试图使用groupby命令以某种方式获取一个查询中时间戳的两个值,然后删除另一个查询中的行。请显示该代码,以便我们可以提供更多帮助。@DarshanThanki该代码尚不存在,这就是问题所在。尝试得很好,但它在本地对我不起作用。它并没有限制每个小组只有10条记录。@Rosssmithiii。这很奇怪。查询没有做任何复杂的事情。它只选择要保留的20条记录,并删除其余的记录。会发生什么?你确定A和B能唯一地识别每一行吗?我不确定故障在哪里,但看看它的实际情况。请注意,我的第一个答案是完全错误的,但看到你的答案引导我朝着正确的方向前进,所以你应该为我的答案获得荣誉@罗斯史密斯二世。正如我所怀疑的,您的数据直接与您问题中的陈述“ColA和ColB唯一标识一行”相矛盾。如果这不是真的,那么上面的查询将不起作用。然而,它应该回答你原来的问题。你是对的!你的问题确实有效:我真诚的道歉!很好的尝试,但在本地对我不起作用。它并没有限制每个小组只有10条记录。@Rosssmithiii。这很奇怪。查询没有做任何复杂的事情。它只选择要保留的20条记录,并删除其余的记录。会发生什么?你确定A和B能唯一地识别每一行吗?我不确定故障在哪里,但看看它的实际情况。请注意,我的第一个答案是完全错误的,但看到你的答案引导我朝着正确的方向前进,所以你应该为我的答案获得荣誉@罗斯史密斯二世。正如我所怀疑的,您的数据直接与您问题中的陈述“ColA和ColB唯一标识一行”相矛盾。如果这不是真的,那么上面的查询将不起作用。然而,它应该回答你原来的问题。你是对的!你的问题确实有效:我真诚的道歉!