というよりは「最新○件を残してあとは消すクエリが欲しい」としたらこうやれば良さそう。
例えば、こういうテーブルがあって
CREATE TABLE `test` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`k` varchar(127) NOT NULL,
`v` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx` (`k`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
こういうデータがあったとする
mysql> SELECT * FROM test;
+----+------+-------+
| id | k | v |
+----+------+-------+
| 1 | key2 | value |
| 2 | key3 | value |
| 3 | key1 | value |
| 4 | key2 | value |
| 5 | key3 | value |
| 6 | key1 | value |
| 7 | key2 | value |
| 8 | key3 | value |
| 9 | key1 | value |
| 10 | key2 | value |
| 11 | key3 | value |
| 12 | key1 | value |
| 13 | key2 | value |
| 14 | key3 | value |
| 15 | key1 | value |
| 16 | key2 | value |
| 17 | key3 | value |
| 18 | key1 | value |
| 19 | key2 | value |
| 20 | key3 | value |
| 21 | key1 | value |
+----+------+-------+
21 rows in set (0.00 sec)
これの k = key1 のなかで id が大きい方3件を残して消したい場合、こういうクエリを発行すると良い。
DELETE FROM test WHERE k = 'key1' AND id NOT IN (
SELECT id FROM (
SELECT id FROM test WHERE k = 'key1' ORDER BY id DESC LIMIT 3
) t
)
すると、いい感じに消えてくれる。
mysql> SELECT * FROM test WHERE k = 'key1' ORDER BY id DESC;
+----+------+-------+
| id | k | v |
+----+------+-------+
| 21 | key1 | value |
| 18 | key1 | value |
| 15 | key1 | value |
| 12 | key1 | value |
| 9 | key1 | value |
| 6 | key1 | value |
| 3 | key1 | value |
+----+------+-------+
7 rows in set (0.00 sec)
mysql> DELETE FROM test WHERE k = 'key1' AND id NOT IN (SELECT id FROM (SELECT id FROM test WHERE k = 'key1' ORDER BY id DESC LIMIT 3) t);
Query OK, 4 rows affected (0.00 sec)
mysql> SELECT * FROM test;
+----+------+-------+
| id | k | v |
+----+------+-------+
| 1 | key2 | value |
| 2 | key3 | value |
| 4 | key2 | value |
| 5 | key3 | value |
| 7 | key2 | value |
| 8 | key3 | value |
| 10 | key2 | value |
| 11 | key3 | value |
| 13 | key2 | value |
| 14 | key3 | value |
| 15 | key1 | value |
| 16 | key2 | value |
| 17 | key3 | value |
| 18 | key1 | value |
| 19 | key2 | value |
| 20 | key3 | value |
| 21 | key1 | value |
+----+------+-------+
17 rows in set (0.00 sec)
mysql> SELECT * FROM test WHERE k = 'key1' ORDER BY id DESC;
+----+------+-------+
| id | k | v |
+----+------+-------+
| 21 | key1 | value |
| 18 | key1 | value |
| 15 | key1 | value |
+----+------+-------+
3 rows in set (0.00 sec)
(なんだかへんてこなクエリになってる(サブクエリの中にサブクエリが入ってる)のは、MySQL が WHERE IN で使ったサブクエリの中で LIMIT が使えないという制約があるからである。ポスグレとかはそのままいけるかも?)