簡體   English   中英

MYSQL刪除所有行,但select上的相同查詢只返回3行

[英]MYSQL delete all rows, but the same query on select return only 3 rows

我無法理解為什么select和delete的相同查詢具有不同的行為。
我需要刪除除5個最新行之外的所有行。
我知道我的這個任務的解決方案並不好,但我的問題是為什么MySQL沒有刪除相同的行,返回select為同一個查詢子句

看代碼

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 |
# +----+-----+------------+

我哭了;

我們可以嘗試在這里執行刪除限制連接:

DELETE t1
FROM tbl t1
LEFT JOIN
(
    SELECT id
    FROM tbl
    ORDER BY created_at DESC
    LIMIT 5
) t2
    ON t1.id = t2.id
WHERE
    t2.id IS NULL;

這種反連接背后的想法是,我們將刪除任何與前五個記錄之一匹配的記錄,這些記錄按created_at列的順序遞減。

請注意,我們不能WHERE IN此處使用WHERE IN查詢,因為MySQL將返回此版本尚不支持LIMIT的可怕錯誤消息。

使用LIMITOFFSET獲取要刪除的最高ID:

set @last_id_to_delete = (
  select id
  from tbl
  order by id desc
  limit 1
  offset 5
);

然后刪除ID等於或小於obove值的所有行:

delete tbl
from tbl
where id <= @last_id_to_delete;

DB-小提琴

您可以將兩個查詢合並為一個。 使用WHERE子句中的子查詢:

delete tbl
from tbl
where id <= (select id from(
  select id
  from tbl
  order by id desc
  limit 1
  offset 5
)x);

(請注意,您需要將子查詢結果包裝到派生表中,以避免錯誤:“您無法在FROM子句中為更新指定目標表'tbl'。”

DB-FIDLE

或者通過加入單行子查詢:

delete t
from tbl t
join (
  select id as last_id_to_delete
  from tbl
  order by id desc
  limit 1
  offset 5
) x on t.id <= x.last_id_to_delete;

DB-FIDLE

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM