MySQL如何合并重复记录

Posted

技术标签:

【中文标题】MySQL如何合并重复记录【英文标题】:How to merge duplicate records in MySQL 【发布时间】:2020-01-07 02:30:00 【问题描述】:

我有 1100 万行的 post_view_counters 表。

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 的所有行视图 更新表格后的结果应该是这样的

id    post_id    start_date    end_date    views
_________________________________________________
1       55          XXXX         YYYY        92

【问题讨论】:

表是 MyISAM 还是 InnoDB ?表上是否定义了任何索引?您是否要直接在生产中进行此更改(例如当您的应用程序实际使用表时)?由于是一张大桌子,答案会因影响生产的严重程度而异。 start_date end_date 对于所有行都应该相同 所以您想删除重复项,以便表格上只剩下一行,但查看次数正确 @RiggsFolly 是的,只有一行更新了视图 【参考方案1】:

首先,您必须为每个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;

由于这是一个大表,因此需要适当的索引以使进程尽可能快地运行。 请参阅demo。 对于此表:

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     |

【讨论】:

【参考方案2】:

我会采取安全的方法:

首先,新建一个表——

CREATE TABLE post_view_counters_new LIKE post_view_counters;

然后将数据插入到新表中——(@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; 

之后,比较新表和旧表的数据。满意后,将旧表重命名为“post_view_counters_old”,并将“post_view_counters_new”重命名为“post_view_counters”。因此,如果您在新表中缺少任何内容,您仍然可以参考旧表。

【讨论】:

好答案+1;但同样是直接delete 更好还是create .. insert 方法;从性能的角度来看,这完全取决于实际存在多少重复行。【参考方案3】:

你可以试试下面-

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

【讨论】:

伙计们,请参阅comment 并在下方回答【参考方案4】:

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

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 ,我需要在 table 中更新所有行 各位,见comment并在下方回答

以上是关于MySQL如何合并重复记录的主要内容,如果未能解决你的问题,请参考以下文章

合并重复记录,根据MySql中的条件值保留一些数据

重复记录的合并列值[重复]

mysql union和union all的区别

c#中同一个Datatable中的如何把重复的记录合并起来,

MySQL进阶4

如何检查Mysql表中是不是存在记录[重复]