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唯一标识一行”相矛盾。如果这不是真的,那么上面的查询将不起作用。然而,它应该回答你原来的问题。你是对的!你的问题确实有效:我真诚的道歉!