如何合并 MySQL 中的重复记录

How to merge duplicate records in MySQL

我有 post_view_counters table 有 1100 万行。

id    post_id    start_date    end_date    views
_________________________________________________
1       55          XXXX         YYYY        90
2       55          XXXX         YYYY        1
3       55          XXXX         YYYY        1

由于某种原因(后端错误)存在重复记录,这些记录已修复。 我需要合并具有相同 post_idstart_dateend_date 的所有行视图 更新后结果应该是这样 table

id    post_id    start_date    end_date    views
_________________________________________________
1       55          XXXX         YYYY        92

对于相同的 post_id , start_date , end_date 你可以使用聚合函数 作为 min(id) 、 sum(view ) 和分组

select min(id) id,  post_id ,   start_date ,   end_date ,   sum( views) views
from my_table  
group  by  post_id ,   start_date ,   end_date

你可以试试下面的-

select min(id),post_id,    start_date ,   end_date,sum(views)
from tablename
group by post_id, start_date, end_date

我会采取安全的方法:

首先,创建一个新的 table -

CREATE TABLE post_view_counters_new LIKE post_view_counters;

然后将数据插入到新的table-(@scaisEdge的语法)

INSERT INTO post_view_counters_new 
SELECT MIN(id) id,  post_id ,   start_date ,   end_date ,   SUM( views) views
FROM post_view_counters
GROUP  BY  post_id ,   start_date ,   end_date; 

之后,比较新table和旧table之间的数据。满意后,将旧的 table 重命名为 'post_view_counters_old' 并将 'post_view_counters_new' 重命名为 'post_view_counters'。因此,如果您在新 table 中遗漏了任何内容,您仍然可以参考旧 table.

首先,您必须为每个 post_id, start_date, end_date:

用最小值 id 更新行
update tablename t inner join (
  select sum(views) views, min(id) id from tablename
  group by post_id, start_date, end_date
) tt
on tt.id = t.id 
set t.views = tt.views;

然后删除所有其他 ID,只保留最小值 id

delete t 
from tablename t inner join tablename tt
on tt.post_id = t.post_id 
and tt.start_date = t.start_date and tt.end_date = t.end_date 
and t.id > tt.id;

由于这是一个很大的 table,因此需要适当的索引以使过程 运行 尽可能快。

demo.
为此 table:

CREATE TABLE tablename (
  `id` INTEGER,
  `post_id` INTEGER,
  `start_date` VARCHAR(4),
  `end_date` VARCHAR(4),
  `views` INTEGER
);

INSERT INTO tablename
  (`id`, `post_id`, `start_date`, `end_date`, `views`)
VALUES
  ('1', '55', 'XXXX', 'YYYY', '90'),
  ('2', '55', 'XXXX', 'YYYY', '1'),
  ('3', '55', 'XXXX', 'YYYY', '1'),
  ('4', '65', 'AAAA', 'BBBB', '10'),
  ('5', '65', 'AAAA', 'BBBB', '2'),
  ('6', '65', 'AXXX', 'BYYY', '100'),
  ('7', '65', 'AXXX', 'BYYY', '200'),
  ('8', '75', 'CCCC', 'CCCC', '1');

结果:

| id  | post_id | start_date | end_date | views |
| --- | ------- | ---------- | -------- | ----- |
| 1   | 55      | XXXX       | YYYY     | 92    |
| 4   | 65      | AAAA       | BBBB     | 12    |
| 6   | 65      | AXXX       | BYYY     | 300   |
| 8   | 75      | CCCC       | CCCC     | 1     |