数据库有订单表和订单明细表两张表,订单表与订单明细表的关系为一对多,通过订单ID作为外键进行关联,订单表的订单号字段本应设计成唯一约束,但由于数据库约束未在表里体现,并且由于业务操作的一些原因,导致订单表里出现重复的订单号,并且这些订单记录下面都关联了货品,现需要将重复的订单记录删除,同一个订单号只保留一条记录,其余被删除的订单表记录下面的明细记录全部移到保留的那条记录上面。表结构如下所示(表结构有做简化):
订单表t_order:
CREATE TABLE `t_order` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`order_no` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;
订单明细表t_order_detail:
CREATE TABLE `t_order_detail` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`order_id` int(11) DEFAULT NULL,
`sku` varchar(50) DEFAULT NULL,
`qty` int(9) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `order_id_fk` (`order_id`),
CONSTRAINT `order_id_fk` FOREIGN KEY (`order_id`) REFERENCES `t_order` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8;
select order_no,count(1) from t_order group by order_no having count(1) > 1;
2、根据订单号查询订单明细表留下的和删除的ID
select order_id,retain_id from t_order_detail detail
inner join (
select od2.id as retain_id,od1.id as del_id from t_order od1
inner join (select id,order_no from t_order where order_no in (
'20180211001',
'20180211002',
'20180211003',
'20180211004'
) group by order_no
) od2 on od2.order_no = od1.order_no and od1.id <> od2.id
) header on detail.order_id = header.del_id
group by order_id,retain_id
select id,order_no from t_order where order_no in (
'20180211001',
'20180211002',
'20180211003',
'20180211004'
) group by order_no
里面的order_no就是利用第1步查询的结果,通过订单号进行分组,得到的id将是数据库记录默认排序靠前的记录,这些ID对应的订单表数据将是最终要保留下来的记录。
2)外一层查询:
select od2.id as retain_id,od1.id as del_id from t_order od1
inner join (select id,order_no from t_order where order_no in (
'20180211001',
'20180211002',
'20180211003',
'20180211004'
) group by order_no
) od2 on od2.order_no = od1.order_no and od1.id <> od2.id
update t_order_detail detail
inner join (
select od2.id as retain_id,od1.id as del_id from t_order od1
inner join (select * from t_order where order_no in (
'20180211001',
'20180211002',
'20180211003',
'20180211004'
) group by order_no
) od2 on od2.order_no = od1.order_no and od1.id <> od2.id
) header on detail.order_id = header.del_id
set detail.order_id = header.retain_id
select od.id,od.order_no from t_order od
left join t_order_detail detail on od.id = detail.order_id
where detail.id is null and od.order_no in (
'20180211001',
'20180211002',
'20180211003',
'20180211004'
)
delete from t_order where id in (
select od.id from (select * from t_order) od
left join t_order_detail detail on od.id = detail.order_id
where detail.id is null and od.order_no in (
'20180211001',
'20180211002',
'20180211003',
'20180211004'
))
5、核验数据
select order_no,count(1) from t_order group by order_no having count(1) > 1;