2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

MySQL で FIFO っぽいことを実現したい

Posted at

というよりは「最新○件を残してあとは消すクエリが欲しい」としたらこうやれば良さそう。

例えば、こういうテーブルがあって

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 が使えないという制約があるからである。ポスグレとかはそのままいけるかも?)

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?