Ada*_*tan 5 mysql delete subquery
考虑下表:
mysql> DESCRIBE pixels;
+---------------+-------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+-------------+------+-----+-------------------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| pixel_id | varchar(32) | NO | MUL | NULL | |
| creation_time | timestamp | NO | MUL | CURRENT_TIMESTAMP | |
| pixel | mediumblob | NO | | NULL | |
+---------------+-------------+------+-----+-------------------+----------------+
4 rows in set (0.04 sec)
Run Code Online (Sandbox Code Playgroud)
用一些数据:
mysql> SELECT * FROM pixels;
+----+----------------------------------+---------------------+----------------------------------+
| id | pixel_id | creation_time | pixel |
+----+----------------------------------+---------------------+----------------------------------+
| 1 | 0d1b042671e0f8c1d1f226abe923583c | 2012-07-01 14:42:26 | 2d8292a62e89fcbf8b1592cf53f0dc86 |
| 2 | 9192b7491ac9321ed67c198834965580 | 2012-07-01 14:42:26 | f41a4a3e1a5f2f25c02f2e377627355c |
| 3 | 82b6ad645a4c75a552c0ddfd8d07c38a | 2012-07-01 14:42:27 | bffd2be16fcb82d0592aaa00fe0ebb9d |
| 4 | de41f4932ee7e90bed2e26d4e7e1937a | 2012-07-01 14:42:27 | 6632df3642ce3465ee5160126f20d837 |
| 5 | f98ac2c09574e2accb6cff709ac8a97f | 2012-07-01 14:42:27 | 00d1a3d9e9b51d7e5f66120203189107 |
| 6 | e90a3233fd9054fb3c23d04b03a8dde8 | 2012-07-01 14:42:27 | 4d20a996a46b9767d8c3f6708cb0ce88 |
| 7 | 08177f9f44f3d6fa515bd1a1983a7b45 | 2012-07-01 14:42:28 | ed3a572da6d05d34f5928035bc67d5be |
| 8 | 9d9138ffb7df537d61276a91e837a327 | 2012-07-01 14:42:28 | 3be6876351254ffa4a00364cd3e8c10e |
+----+----------------------------------+---------------------+----------------------------------+
Run Code Online (Sandbox Code Playgroud)
我正在尝试删除除最后 5 行之外的所有记录。“最后”由 确定id,creation_time可能重复。
我试过了:
mysql> SELECT id FROM pixels ORDER BY creation_time DESC LIMIT 1 OFFSET 5;
Run Code Online (Sandbox Code Playgroud)
并得到了合理的答案:
+----+
| id |
+----+
| 3 |
+----+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
我尝试将其用作子查询:
mysql> DELETE FROM pixels WHERE id <
(SELECT id FROM pixels ORDER BY creation_time DESC LIMIT 1 OFFSET 5);
ERROR 1093 (HY000): You can't specify target table 'pixels' for update in FROM clause
Run Code Online (Sandbox Code Playgroud)
尝试了另一种方法:
mysql> DELETE FROM pixels WHERE id NOT IN
(SELECT id FROM pixels ORDER BY creation_time DESC LIMIT 5);
ERROR 1235 (42000): This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
Run Code Online (Sandbox Code Playgroud)
那么,如何删除除 N 个最近的记录之外的所有记录?
您需要稍微更改您的子查询方法 - 将条件从WHERE子句移动到连接,以绕过 MySQL 限制。
如果id和creation_time始终定义相同的顺序,则可以使用以下命令:
DELETE p
FROM
pixels AS p
JOIN
( SELECT id
FROM pixels
ORDER BY id
LIMIT 1 OFFSET 4
) AS lim
ON p.id < lim.id ;
Run Code Online (Sandbox Code Playgroud)
由于这可能不是真的,并且两个排序有时可能不同,导致删除的行数比 5 多或少,您可以使用它,这会更准确,但对于大表可能会更慢:
DELETE p
FROM
pixels AS p
JOIN
( SELECT creation_time, id
FROM pixels
ORDER BY creation_time DESC, id DESC
LIMIT 1 OFFSET 4
) AS lim
ON p.creation_time < lim.creation_time
OR p.creation_time = lim.creation_time AND p.id < lim.id ;
Run Code Online (Sandbox Code Playgroud)