一條語句刪除數據庫中的重複記錄(數據量較大,百萬級數據,注意性能問題)
此類問題比較常見,在平常的開發當中,如何使用一條語句就能夠做到呢? 並且效率還要很快,下邊給出一種刪除重複數據保留一條的方案. 希望大家有好的思路可以評論分享.這邊爲了方便理解,給出我本地使用的sql案例,方便大家測試和修改
首先說下思路:
- 把重複數據查出來作爲一個臨時表temp
- 保留一組重複數據中主鍵id最小的記錄(刪除的時候要用)
- 兩個表連接進行刪除操作,刪除Where條件:重複條件相同,並且id>min(id)
數據表字段及說明
consum_record表數據及結構下載
表結構如下:
id主鍵,注意重複的列爲user_id(用戶id),monetary(消費金額),consume_time(消費時間),也就是說,同一個顧客同一個時間消費金額數是不可能存在多條數據的, 我們要對數據庫中記錄坐下排重
其中摘錄出來幾條重複數據供大家理解題設
id | user_id | monetary | consume_time | consume_type |
---|---|---|---|---|
2552 | 321 | 4 | 1495075537 | 1 |
2553 | 321 | 4 | 1495075537 | 1 |
2554 | 321 | 4 | 1495079932 | 1 |
2555 | 111 | 6 | 1495079932 | 1 |
2556 | 111 | 6 | 1495079932 | 1 |
2557 | 156 | 12 | 1495079939 | 1 |
2558 | 156 | 12 | 1495079939 | 1 |
2559 | 156 | 12 | 1495079939 | 1 |
SQL展示
DELETE consum_record
FROM
consum_record,
(
SELECT
min(id) id,
user_id,
monetary,
consume_time
FROM
consum_record
GROUP BY
user_id,
monetary,
consume_time
HAVING
count(*) > 1
) temp
WHERE
consum_record.user_id = temp.user_id
and consum_record.monetary = temp.monetary
and consum_record.consume_time = temp.consume_time
AND consum_record.id > temp.id;
思路:
- 首先就是將user_id,monetary,consume_time這三個字段進行group by,將
count(*)>1
篩選出來
min(id) id 每個重複組當中的最小id很關鍵,刪除數據的時候做篩選使用 也可以使用max(id)
SELECT
min(id) id,#每個重複組當中的最小id很關鍵,刪除數據的時候做篩選使用 也可以使用max(id)
user_id,
monetary,
consume_time
FROM
consum_record
GROUP BY
user_id,
monetary,
consume_time
HAVING
count(*) > 1
- 接下來使用基礎表,和查出來的重複數據做關聯(根據三個重複字段做關聯), 然後根據每組重複數據
consumer_record.id> temp.id
刪除相應數據
總結:
要深刻理解group by的原理, 根據相應的條件分組
刪除的時候temp表其實就是作爲一個篩選條件而存在的表,這時候可以兩個表做關聯篩選出需要的行