2012-10-07 79 views
0

我有一個表,看起來有點像這樣: -優化的SQL查詢來刪除行

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 

可樂COLB唯一標識一行。但是,它不是主要關鍵。 ColC可以是0或1. ColD是日期時間字段。 我需要只保留10行(或更少)從這個表中有colC爲0和10行(或更少)colC爲1,最大總數沒有。的行數爲20.這10行(每個)是最近的行,即最近的10行(基於colD值),其中0爲colC值。類似地,ColC值保持爲1的(最多)10行應該是具有1個ColC值的前10行。

目前,我正在發射4個查詢以實現此目的。我將每個colC值的查詢分別作爲0和1來獲取第11行(或更少)的時間戳。然後對於獲得的每個值,我激發另一個查詢來刪除所有「較舊」的行。

我可以啓動一個單一的查詢來實現嗎?如果不是,那麼最佳解決方案是什麼?

PS: - 我在我的應用程序中使用活動記錄,將不得不相應地修改查詢。

+0

你有什麼話就可以做什麼?你有沒有工作的查詢? –

+0

我試圖使用groupby命令以某種方式獲取一個查詢中的時間戳值,然後刪除另一個查詢中的行。 –

+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行中的一個單獨的表,截斷原始表,然後將其插入。

+0

不錯的嘗試,但它在本地並不適合我。它並沒有將每個組限制爲只有10條記錄。 –

+0

@RossSmithII。 。 。這很奇怪。該查詢沒有做任何複雜的事情。它只是選擇20條記錄來保留和刪除其餘記錄。怎麼了?你確定A和B是唯一標識每一行的嗎? –

+0

我不確定毛刺在哪裏,但看看http://sqlfiddle.com/#!2/51670/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;