在MYSQL中删除基于组的记录

时间:2014-03-07 13:44:37

标签: mysql group-by sql-delete

我无法提出一个查询,这将允许我只保留用户的最新订单(也许更好的方式来说这是删除所有旧订单):

CREATE TABLE orders(id integer, created_at datetime, user_id integer, label nvarchar(25));

INSERT INTO orders values(1, now(), 1, 'FRED FIRST');

INSERT INTO orders values(2, DATE_ADD(now(), INTERVAL 1 DAY), 1, 'FRED SECOND');

INSERT INTO orders values(3, DATE_ADD(now(), INTERVAL 2 DAY), 1, 'FRED THIRD');

INSERT INTO orders values(4, DATE_ADD(now(), INTERVAL 1 DAY), 3, 'BARNEY FIRST');

SELECT * FROM orders;

'1','2014-03-07 08:39:36','1','FRED FIRST'
'2','2014-03-08 08:39:36','1','FRED SECOND'
'3','2014-03-09 08:39:36','1','FRED THIRD'
'4','2014-03-08 08:39:36','3','BARNEY FIRST'

我想运行一个查询,这将留下FRED的第三个订单和BARNEY的第一个订单。应删除FRED FIRST和FRED SECOND,因为它们不是FRED的最新订单。

有关如何使用单个查询执行此操作的任何想法?

编辑:在发布之后,我发现了一些有用的东西(它正在做我想做的事) - 但它看起来有点乱:

DELETE  old_orders
FROM orders old_orders
left outer join(
SELECT MAX(created_at) as created_at, user_id
FROM orders
GROUP BY user_id) new_orders
ON new_orders.user_id = old_orders.user_id and new_orders.created_at = old_orders.created_at
WHERE new_orders.user_id is null;

2 个答案:

答案 0 :(得分:1)

使用嵌套查询,如下所示:

DELETE FROM orders
WHERE id NOT IN (
  SELECT id FROM (
    select id from orders o JOIN (
      select user_id, max(created_at) t from orders group by user_id
    ) o1 ON o.user_id = o1.user_id AND o.created_at = o1.t
  ) AS tmp
)

工作小提琴:http://sqlfiddle.com/#!2/56d913/1

答案 1 :(得分:0)

您可能实现此目的的一种方法是为行设置一个标志,指示它是最近的订单。因此,当您下达新订单时,您将清除该客户的其他订单上的标记,并为您插入的行设置标记。然后你的DELETE查询可以删除所有没有设置该标志的订单。