2014-09-26 51 views
0

我想刪除大於30天的表的所有記錄,但保留每個ID的最後(最年輕)2記錄。 我做了一些嘗試與極限2和組合,但沒有得到解決方案附近。有沒有人有建議?複雜的刪除查詢

DROP TABLE IF EXISTS mytable; 

CREATE TABLE `mytable` (
    `timestamp` datetime NOT NULL, 
    `id` int(11) NOT NULL, 
    `data` varchar(100) NOT NULL, 
    PRIMARY KEY (`id`,`timestamp`) 
); 

INSERT INTO mytable VALUES 
('2014-08-12',22,'data'), 
('2014-08-13',22,'data'), 
('2014-08-14',22,'data'), 
('2014-08-15',22,'data'), 
('2014-08-16',54,'data'), 
('2014-08-16',22,'data'), 
('2014-08-17',54,'data'), 
('2014-08-18',54,'data'), 
('2014-08-19',54,'data'); 


Expected Result 
2014-08-15,22,data 
2014-08-16,22,data 
2014-08-18,54,data 
2014-08-19,54,data 

這是我迄今爲止

sql = 'Delete from mytable where timestamp < DATE_SUB(NOW(), INTERVAL 30 DAY)'; 
+0

這個數據集並沒有很好的代表性,因爲如果你放棄30天規則,你仍然會得到相同的結果! – Strawberry 2014-09-26 10:27:22

+1

而在數據庫中你有'datetime'不是'date',所以在數據中你應該有'2014-08-19 12:35:57'例如 – DarkSide 2014-09-26 10:28:15

+0

嗨 - 我只是爲了更好的可讀性而舉行日期 – ratmalwer 2014-09-26 10:43:43

回答

1
DELETE t 
FROM mytable t 
JOIN (
    SELECT id, SUBSTRING_INDEX(group_ts, ',', 2) AS two_ts 
    FROM (
    SELECT id, GROUP_CONCAT(timestamp ORDER BY timestamp DESC) AS group_ts 
    FROM mytable 
    WHERE timestamp < DATE_SUB(NOW(), INTERVAL 30 DAY) 
    GROUP BY id 
) ag 
) tg ON tg.id = t.id AND FIND_IN_SET(t.timestamp, tg.two_ts) = 0 
WHERE timestamp < DATE_SUB(NOW(), INTERVAL 30 DAY) 

我不認爲它在大數據集上表現良好。雖然它會一直工作,直到日期組不超過group_concat_max_len。每組參加k條目的想法摘自xaprb blog post的評論。使用this SQL Fiddle玩查詢。

+0

是的 - 這樣做的工作! 我改變了查詢,並在SELECT中刪除了第一個:WHERE timestamp ratmalwer 2014-09-27 10:53:29

-1

不正確的解決方法:

DELETE FROM mytable a 
WHERE a.timestamp < DATE_SUB(NOW(), INTERVAL 30 DAY)' 
    AND (a.id, a.timestamp) NOT IN (
     SELECT b.id, b.timestamp 
     FROM mytable b 
     GROUP BY b.id 
     ORDER BY b.id, b.timestamp desc 
     LIMIT 2 
    ) 

希望正確的解決辦法:

DELETE FROM mytable a 
    LEFT JOIN (
     SELECT c.id, count(1) as cnt 
     FROM mytable c 
     GROUP BY c.id 
    ) b on a.id = b.id 
WHERE a.timestamp < DATE_SUB(NOW(), INTERVAL 30 DAY)' 
    AND b.cnt > 2 
+0

Select選擇節目該ID只有一次 - 與我發生的一樣 – ratmalwer 2014-09-26 10:31:12

+0

是的第一個解決方案是錯誤的。你可以請再測試一下嗎?我現在只是沒有mysql來測試自己。 – DarkSide 2014-09-26 10:32:02

+0

你如何確保最舊的記錄被刪除?不知何故,我錯過了一個訂單。或者我忽略了什麼? – ratmalwer 2014-09-26 10:42:37