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 是一个日期时间字段。我只需要从该表中保留 10 行(或更少),其中 colC 为 0 和 10 行(或更少), colC 为 1,以获得最大总数。行数为 20。这 10 行(每行)是最近的行,即最近的 10 行(基于 colD 值)的 colC 值为 0。同样,保留的(最多)10 行 ColC 值为 1,应该是前 10 行 ColC 值为 1。

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

我可以触发一个查询来实现这一目标吗?如果不是,那么对此的最佳解决方案是什么?

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

4

2 回答 2

3

这将起作用(请参阅http://sqlfiddle.com/#!2/161af/1):

delete from t
where not exists (select 1
                  from ((select A, B
                         from t
                         where C = 0
                         order by D desc
                         limit 10
                        ) union all
                        (select A, B
                         from t
                         where C = 1
                         order by D desc
                         limit 10
                        )
                       ) a
                  where a.A = t.A and a.B = t.B
                 )

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

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

于 2012-10-07T18:32:06.440 回答
1

这应该适合你:

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

运行上述查询后,

SELECT 
  C,
  COUNT(*),
  MIN(D),
  MAX(D)
FROM 
  ex
GROUP BY
  C
ORDER BY
  C

返回:

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

有关工作示例,请参阅SQL Fiddle 。

请注意,如果您要删除超过 50% 的数据,您可能会发现将SELECT要保留到新表中的记录更好,然后RENAME将此表保留到现有表中。

这是一个例子:

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;
于 2012-10-07T18:13:33.083 回答