需求
有一个表一开始没有做唯一索引导致数据有重复的数据,为了查询时候代码不做去重打算在表创建唯一索引,但是数据库已经有重复的数据了,需要把重复的数据大于2两条的全部删除
CREATE TABLE `hub_user_group` (
`id` bigint(20) NOT NULL,
`uid` bigint(20) NOT NULL COMMENT '用户id',
`group_type` int(11) NOT NULL DEFAULT '0' COMMENT '分组类型 1=黑名单 2=白名单 3=支付-白名单 ',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
`create_user` varchar(255) NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_user` varchar(255) NOT NULL COMMENT '修改人',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
`delete_flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否删除',
PRIMARY KEY (`id`),
KEY `idx_uid` (`uid`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户分组';
实现
DELETE FROM hub_user_group
WHERE id IN (
SELECT id FROM (
SELECT T1.id
FROM hub_user_group T1
JOIN hub_user_group T2
ON T1.uid = T2.uid
AND T1.group_type = T2.group_type
AND T1.id > T2.id
) AS subquery
);
解释
这条 SQL 语句的目的是删除 hub_user_group 表中重复的记录,保留每组 uid 和 group_type 中 id 最小的记录。以下是对这条语句的详细解释:
语句结构
DELETE FROM hub_user_group
WHERE id IN (
SELECT id FROM (
SELECT T1.id
FROM hub_user_group T1
JOIN hub_user_group T2
ON T1.uid = T2.uid
AND T1.group_type = T2.group_type
AND T1.id > T2.id
) AS subquery
);
分步解释
-
外层
DELETE语句DELETE FROM hub_user_group WHERE id IN ( -- Subquery here );这部分是删除
hub_user_group表中满足条件的记录。具体条件由内层子查询决定。 -
内层子查询
SELECT id FROM ( -- Inner subquery here ) AS subquery这个子查询从
hub_user_group表中选择需要删除的记录的id。为了避免 MySQL 的限制(即不能在DELETE语句中直接引用正在修改的表),这里使用了双重子查询。 -
最内层子查询
SELECT T1.id FROM hub_user_group T1 JOIN hub_user_group T2 ON T1.uid = T2.uid AND T1.group_type = T2.group_type AND T1.id > T2.id这个子查询的作用是找到所有需要删除的记录的
id。具体步骤如下:- 表别名:给
hub_user_group表起别名T1和T2。 - 条件
JOIN:将T1和T2表进行连接,条件是T1.uid = T2.uid和T1.group_type = T2.group_type。这意味着我们在比较具有相同uid和group_type的记录。 - 过滤条件:
T1.id > T2.id。这意味着我们只选择那些T1的id大于T2的id的记录。换句话说,对于每组具有相同uid和group_type的记录,我们只选择那些id较大的记录。
这部分子查询的结果是所有需要删除的记录的
id。 - 表别名:给
-
删除操作
外层
DELETE语句使用内层子查询的结果作为条件,删除所有id在这些结果中的记录。
示例
假设你的表 hub_user_group 有以下数据:
id | uid | group_type | data
---|-----|------------|------
1 | 1 | A | ...
2 | 1 | A | ...
3 | 2 | B | ...
4 | 2 | B | ...
5 | 2 | B | ...
执行上述 DELETE 语句后,表中的数据将变为:
id | uid | group_type | data
---|-----|------------|------
1 | 1 | A | ...
3 | 2 | B | ...
所有具有相同 uid 和 group_type 且 id 较大的记录都被删除,只保留每组中 id 最小的记录。
希望这个解释能帮你更好地理解这条 SQL 语句的作用。如果你有任何其他问题或需要进一步的帮助,请随时告诉我。