0

我有一张桌子cartscartitems第二张桌子有一个外键。现在我想删除所有carts超过 3 个月且没有相关的行cartitems。以下查询给了我正确的结果:

SELECT * 
FROM  `carts` c
LEFT OUTER JOIN  `cartitems` i ON (  `c`.`id` =  `i`.`cart_id` ) 
WHERE  `c`.`last_updated` < DATE_SUB(NOW() , INTERVAL 3 MONTH) 
GROUP BY  `c`.`id` 
HAVING COUNT(  `i`.`id` ) = 0;

但我不知道如何将此查询转换为DELETE.

此外,由于表中有大约 1000 万行carts,我会感谢有关如何改进此查询的建议 :-)

4

3 回答 3

1

您可以在不带LIMIT或带 a的情况下运行以下LIMIT命令以批量删除行。

DELETE c
FROM  carts c
WHERE c.last_updated < DATE_SUB(NOW() , INTERVAL 3 MONTH)
  AND NOT EXISTS
      ( SELECT *
        FROM cartitems i 
        WHERE c.id = i.cart_id
     ) 
LIMIT 10000 ;                           --- optional
于 2012-05-21T16:08:54.687 回答
0

存在的查询应该可以工作:

DELETE FROM `carts` WHERE EXISTS (SELECT * 
FROM  `carts` c
LEFT OUTER JOIN  `cartitems` i ON (  `c`.`id` =  `i`.`cart_id` ) 
WHERE  `c`.`last_updated` < DATE_SUB(NOW() , INTERVAL 3 MONTH) 
GROUP BY  `c`.`id` 
HAVING COUNT(  `i`.`id` ) = 0);

此查询应删除结果集中的所有行。

请注意,您可以将星号与 null 或任何其他值交换。

第二次尝试:

DELETE FROM `carts` WHERE `carts`.`id` IN (SELECT `c`.`id` 
FROM  `carts` c
LEFT OUTER JOIN  `cartitems` i ON (  `c`.`id` =  `i`.`cart_id` ) 
WHERE  `c`.`last_updated` < DATE_SUB(NOW() , INTERVAL 3 MONTH) 
GROUP BY  `c`.`id` 
HAVING COUNT(  `i`.`id` ) = 0);

那会生成一个 id 列表(我希望 c.id 是您的主键)并删除与该 id 相关的所有行。

于 2012-05-21T15:16:56.967 回答
0

你可以试试这个

DELETE FROM 
(
    SELECT * 
    FROM  `carts` c
    LEFT OUTER JOIN  `cartitems` i ON (  `c`.`id` =  `i`.`cart_id` ) 
    WHERE  `c`.`last_updated` < DATE_SUB(NOW() , INTERVAL 3 MONTH) 
    GROUP BY  `c`.`id` 
    HAVING COUNT(  `i`.`id` ) = 0
);

不过我不确定:)

于 2012-05-21T16:04:43.800 回答