1

我有一个这样的 MySql 表,

Session_Id Subscriber_Id 状态
-------------------------------------------
abc 1234 开始
bcd 1235 开始
bcd 1235 完成

而且我需要删除状态为“已开始”的行,只有在后面跟着“完成”。这是一个巨大的表,所以我一次要删除 1000 条记录。

我阅读了一些类似的线程, Multiple-table DELETE LIMIT , DELETE FROM `table` AS `alias` ... WHERE `alias`.`column` ... 为什么语法错误?

并尝试了以下查询,

mysql> delete a.* from FSESSION as a, FSESSION as b where a.status='Started' and b.status='Finished' and a.session_id=b.session_id limit 1000;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'limit 1000' at line 1  ----> If I remove 'limit' this works

mysql> DELETE FROM v USING `FSESSION` AS v WHERE status = 'Started' and exists(select 0 from FSESSION t where t.status='Finished' and v.session_id=t.session_id) limit 1000;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'limit 1000' at line 1 ---->

即使删除限制也不起作用。

我使用 MySql 版本 5.1.56-ndb-7.1.15。请提出一种方法来做到这一点。谢谢!

4

2 回答 2

1

根据您的评论更新

DELETE f
  FROM fsession f JOIN
(
  SELECT session_id, subscriber_id
    FROM fsession
   WHERE status IN('Started', 'Finished')
   GROUP BY Session_Id, Subscriber_Id
  HAVING MAX(status = 'Started')  > 0
     AND MAX(status = 'Finished') > 0
  LIMIT 1000 -- limit here means how many pairs of rows, so it's effectively 2x rows
) q ON f.session_id = q.session_id
   AND f.subscriber_id = q.subscriber_id

要知道删除了多少行,请使用ROW_COUNT()

SELECT ROW_COUNT();

这是SQLFiddle演示

于 2013-09-06T07:29:13.300 回答
1

试试这些查询:

CREATE TEMPORARY TABLE FSESSION_TEMP
(
    Temp_Session_Id varchar(255)
);

INSERT INTO FSESSION_TEMP 
(
SELECT a.Session_Id FROM
    FSESSION a, 
    FSESSION b
WHERE 
    a.Status = 'Started' and 
    b.Status = 'Finished' and
    a.Session_ID = b.Session_ID
  LIMIT 2
);


DELETE FROM 
    FSESSION 
WHERE 
    Session_ID in (SELECT * FROM FSESSION_TEMP)
;

DROP TABLE FSESSION_TEMP;

这是SQL 小提琴。我已将 LIMIT 设置为 2 以表明它有效。您仍然需要将其更改为 1000。

您似乎需要为此使用临时表,原因有两个:

1)当您在子查询中使用同一张表时,MySQL 不允许您从表中删除

2) 对于多表语法,DELETE 从每个 tbl_name 中删除满足条件的行。在这种情况下,不能使用 ORDER BY 和 LIMIT(直接取自 MYSQL DELETE 手册


有一种方法可以规避限制,方法是使用DELETE语法 withJOIN并将原始表(将从中删除行)与派生表(与上述临时表相同)连接起来:

DELETE fdel
FROM 
    FSESSION fdel
  JOIN
    (
    SELECT a.Session_Id 
    FROM
        FSESSION a
      JOIN 
        FSESSION b
      ON a.Session_ID = b.Session_ID
    WHERE 
        a.Status = 'Started' and 
        b.Status = 'Finished' 
      LIMIT 2
    ) ftemp
  ON ftemp.Session_ID = fdel.Session_ID
;
于 2013-09-06T07:20:22.887 回答