MySQL删除/组合类似的行及其引用

时间:2017-02-19 21:02:00

标签: php mysql duplicates

我有2个表:Tags和Post_Tags_relationship

标记表有3列 - ID(主要),标题和网址 Post_Tags_relationship表有2列 - Tag_ID AND Post_ID(主要是两者的组合)

Tags表中有很多类似的标签title和url,我想删除所有复制的记录,并修改Post_Tags_relationship以使用现有的更新已删除的标签ID,如果此更新将返回重复的id错误然后删除它。

因此,如果标记表具有:

ID= 20, Title = News Section, URL = news-section
ID= 68, Title = News Section, URL = news-section

Post_Tags_relationship 有:

Post_ID = 56, Tag_ID = 20
Post_ID = 80, Tag_ID = 20
Post_ID = 500, Tag_ID = 68
Post_ID = 584, Tag_ID = 20
Post_ID = 695, Tag_ID = 20
Post_ID = 695, Tag_ID = 68```

如果我们从Tags表中删除ID 20,Post_Tags_relationship将如下所示:

Post_ID = 56, Tag_ID = 68
Post_ID = 80, Tag_ID = 68
Post_ID = 500, Tag_ID = 68
Post_ID = 584, Tag_ID = 68
Post_ID = 695, Tag_ID = 68 // deplicate Primary key I want this to be removed please.
Post_ID = 695, Tag_ID = 68 // ```

我希望这是有道理的,如果您有任何问题,请告诉我。

2 个答案:

答案 0 :(得分:1)

查找标签重复并将其存储在“临时”表中:

drop table if exists tmp_tags_duplicates;
create table tmp_tags_duplicates
    select t1.id, min(t0.id) as duplicate_of
    from tags t1
    join tags t0 using(title, url)
    where t1.id > t0.id
    group by t1.id;

posts_tags表中查找已插入的重复项(需要删除)。将它们存储在另一个“临时”表中:

drop table if exists tmp_to_delete;
create table tmp_to_delete
    select pt1.*, d.duplicate_of
    from posts_tags pt1
    join tmp_tags_duplicates d on d.id = pt1.tag_id
    join posts_tags pt0 
      on  pt0.post_id = pt1.post_id
      and pt0.tag_id  = d.duplicate_of;

posts_tags中查找需要更新的条目。将它们存储在第三个“临时”表中:

drop table if exists tmp_to_update;
create table tmp_to_update
    select pt1.*, d.duplicate_of
    from posts_tags pt1
    join tmp_tags_duplicates d on d.id = pt1.tag_id
    left join posts_tags pt0 
      on  pt0.post_id = pt1.post_id
      and pt0.tag_id  = d.duplicate_of
    where pt0.tag_id is null;

删除posts_tags中的重复项:

delete pt
from posts_tags pt
join tmp_to_delete t using(post_id, tag_id);

tag_id中更新posts_tags

update posts_tags pt
join tmp_to_update t using(post_id, tag_id)
set pt.tag_id = t.duplicate_of;

删除tags表格中的重复项

delete t
from tags t
join tmp_tags_duplicates using(id);

删除“临时”表格。

drop table tmp_tags_duplicates;
drop table tmp_to_delete;
drop table tmp_to_update;

演示:http://rextester.com/FUWZG89399

现在定义正确的UNIQUE和FOREIGN键,这样您就不需要再次修复它了。

答案 1 :(得分:0)

我将概述如何解决这个问题,我会假设您的表格不大且查询费用不高:

  1. 从标记表中选择所有不同的标题,可以使用DISTINCT关键字来完成。这将使标题不复制:

    SELECT DISTINCT Title FROM Tag

  2. 循环生成的标题,并为每个标题的标签表创建一个新查询,以获取此特定标题的所有重复字段。您最终会获得具有相同标题的行。

  3. 循环具有相同标题的行,将其中的每一行替换为您要保留的ID,同时在Post_Tags_relationship中替换此ID。全部使用UPDATE声明

  4. 完成

    为了避免将来出现这样的问题,请使用外键。 https://www.w3schools.com/sql/sql_foreignkey.asp

    <强>更新

    为了避免由于重复的主键而发生的错误,您可以创建一个数组,并在循环中为每个帖子ID添加它,如果帖子ID已经存在,则从表中删除此记录。像这样:

    $post_ids = array()
    //...
    // Duplicate fields loop
    if ( in_array( $pid, $post_ids ) ) { 
    // The post has the tag already
    // Delete this record from table
    // ..
    
    } else {
       $post_ids[] = $pid
       // Update fields
       // ..
    }