从具有JOIN,GROUP BY和HAVING的表中删除

时间:2012-05-21 15:14:43

标签: mysql

我有一个表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

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

3 个答案:

答案 0 :(得分:1)

您可以在不使用LIMITLIMIT的情况下运行以下内容,以批量删除行。

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

答案 1 :(得分: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相关的所有行。

答案 2 :(得分: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
);

虽然我不确定:)