【发布时间】:2019-11-05 13:49:30
【问题描述】:
我不明白为什么对于 select 和 delete 的相同查询具有不同的行为。
我需要删除除 5 个最新行之外的所有行。
我知道我对这个任务的解决方案不好,但我的问题是为什么 MySQL 不删除相同的行,返回相同查询子句的选择
查看代码
drop table if exists tbl;
create table tbl
(
id serial,
cal date COMMENT 'some column',
created_at datetime default NOW()
);
insert into tbl
values
(default, '2018-07-15', '2018-07-15 12:00'),
(default, '2018-07-16', '2018-07-16 12:00'),
(default, '2018-07-17', '2018-07-17 12:00'),
(default, '2018-07-18', '2018-07-18 12:00'),
(default, '2018-08-01', '2018-08-01 12:00'),
(default, '2018-08-04', '2018-08-04 12:00'),
(default, '2018-08-16', '2018-08-16 12:00'),
(default, '2018-08-17', '2018-08-17 12:00');
select *
from tbl;
# +----+------------+---------------------+
# | id | cal | created_at |
# +----+------------+---------------------+
# | 1 | 2018-07-15 | 2018-07-15 12:00:00 |
# | 2 | 2018-07-16 | 2018-07-16 12:00:00 |
# | 3 | 2018-07-17 | 2018-07-17 12:00:00 |
# | 4 | 2018-07-18 | 2018-07-18 12:00:00 |
# | 5 | 2018-08-01 | 2018-08-01 12:00:00 |
# | 6 | 2018-08-04 | 2018-08-04 12:00:00 |
# | 7 | 2018-08-16 | 2018-08-16 12:00:00 |
# | 8 | 2018-08-17 | 2018-08-17 12:00:00 |
# +----+------------+---------------------+
现在我需要删除 id 为 1,2,3 的行
SET @row_number = 0;
select *
from tbl
where tbl.id in (
select T.id
from (SELECT (@row_number := @row_number + 1) as num, tbl.id
from tbl
order by created_at desc
) as T
where T.num > 5);
# +----+------------+---------------------+
# | id | cal | created_at |
# +----+------------+---------------------+
# | 3 | 2018-07-17 | 2018-07-17 12:00:00 |
# | 2 | 2018-07-16 | 2018-07-16 12:00:00 |
# | 1 | 2018-07-15 | 2018-07-15 12:00:00 |
# +----+------------+---------------------+
现在我使用删除操作
SET @row_number = 0;
delete
from tbl
where tbl.id in (
select T.id
from (SELECT (@row_number := @row_number + 1) as num, tbl.id
from tbl
order by created_at desc
) as T
where T.num > 5);
select * from tbl; # <-- result empty
# +----+-----+------------+
# | id | cal | created_at |
# +----+-----+------------+
我哭了;
【问题讨论】:
-
既然有
id,为什么还要使用@row_number? -
ID可能与row_number不同,例如ID可以以1000开头...
-
我认为您需要重新表述您的问题。
-
我会避免在查询中更新用户变量。它们何时更新将取决于查询计划。在这种情况下,SELECT 查询中的 IN 子查询将转换为半连接,而在单表 DELETE 中则不会。如果您使用多表 DELETE 语法(请参阅oysteing.blogspot.com/2014/07/…),您可能会获得相同的查询计划,但我建议您应该查看 MySQL 8.0 中引入的 windows 函数。
-
谢谢,@oysteing,我像你写的那样尝试:
DELETE part FROM part WHERE p_partkey IN ...它有帮助。我很纳闷,可惜我的知识还不够。
标签: mysql sql sql-delete