我有一张看起来像这样的表: -
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,最大总数为1。这些10行(每行)是最近的行,即10个最近的行(基于colD值),其0为colC值。类似地,保留ColC值为1的(最多)10行应该是前10行,其中1为ColC值。
目前,我正在解决4个查询以实现此目的。我为每个colC值触发一个查询为0和1以获取第11行(或更少)的时间戳。然后,对于获得的每个值,我触发另一个查询以删除所有“较旧”的行。
我可以触发一个查询来实现此目的吗?如果没有,那么最佳解决方案是什么?
PS: - 我在我的应用程序中使用活动记录,并且必须相应地修改查询。
答案 0 :(得分: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行放在单独的表中,截断原始表,然后将其插入。
答案 1 :(得分: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;