【问题标题】:mysql removing duplicates with where clausemysql用where子句删除重复项
【发布时间】:2021-07-26 13:21:27
【问题描述】:

我正在尝试删除具有相同 hid 值的重复记录。

这是小提琴:

https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=86e8ed00cf0a496da490eae5d7aae093

表 product_match_unmatches:

ID  hid flag
1   1   1
2   1   1
3   2   1
4   2   1
5   1   2
6   2   2
7   2   2
8   1   1
9   1   1
10  2   1

现在我想从表中删除重复的 hid 但仅用于 flag = 1。

此查询将删除除最近的duplicates 之外的所有duplicates,但与标志值无关:

DELETE pmu1
FROM dmf_product_match_unmatches as pmu1
LEFT JOIN ( SELECT MAX(ID) as ID, hid
            FROM dmf_product_match_unmatches as pmu2
            GROUP BY hid) pmu3 USING (ID, hid)
WHERE pmu3.ID IS NULL;

我尝试在上述查询中添加 where 子句 flag = 1,但这并没有产生预期的结果。

DELETE pmu1
FROM dmf_product_match_unmatches as pmu1
LEFT JOIN ( SELECT MAX(ID) as ID, hid
            FROM dmf_product_match_unmatches as pmu2
            where flag = 1
            GROUP BY hid
          ) pmu3 USING (ID, hid)
WHERE pmu3.ID IS NOT NULL;

需要的输出是:

ID  hid flag
5   1   2
6   2   2
7   2   2
9   1   1
10  2   1

【问题讨论】:

    标签: mysql sql join left-join


    【解决方案1】:

    你需要在

    DELETE t1
    FROM dmf_product_match_unmatches t1
    JOIN dmf_product_match_unmatches t2 USING (hid, flag)
    WHERE flag = 1 
      AND t1.id < t2.id;
    

    ?

    https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=a5e9e95335573ebedd45cdcd577b5602

    【讨论】:

    • 非常聪明,但是如果表非常大怎么办?加入的记录会爆炸吗?
    • 如果表很大怎么办? ??从大表中删除的行数大于从小表中删除的行数(当然,一般来说)。 连接的记录会爆炸?我不明白你的意思。
    • 如果您有许多重复项,则此连接以及 where 条件将生成包含许多行的结果集。在示例中,选定的行将是 9 而不是 5,有 4 个重复,因为连接会将每一行与所有其他类似的行联系起来,并且 where 将仅过滤少数,如果添加 (11, 1, 1),您将获得 13 行而不是 6 等等.. 好的,对删除没有影响,但可能会影响选择的性能。我不确定优化器是否会自动使用 distinct 子句之类的东西。我只是问。
    • 如果您有许多重复项,则此连接以及 where 条件将生成包含许多行的结果集。 您的话对于 SELECT 是正确的,但 UPDATE / DELETE 有效通过另一种方式,这接近于 WHERE EXISTS 预选。此预选的目的是标记要删除的行。
    【解决方案2】:

    使用row_number

    DELETE pmu1
    FROM dmf_product_match_unmatches pmu1
    JOIN (select id,
             row_number() over(partition by hid order by id desc) rn
           from dmf_product_match_unmatches 
           where flag = 1
         ) as pmu3 ON pmu1.ID = pmu3.ID
    WHERE pmu3.rn > 1;
    

    【讨论】:

      【解决方案3】:

      在sql server中你可以使用EXCEPT集合操作符:

      declare @flag int = 1
      
      delete dmf_product_match_unmatches
      where id in (
      
          select id
          from dmf_product_match_unmatches
          where flag = @flag
      
          except
      
          select max(id) id
          from dmf_product_match_unmatches
          where flag = @flag
          group by hid, flag
      ) 
      

      在mysql中你可以使用NOT EXISTS

      declare @flag int = 1
      
      delete d1
      from dmf_product_match_unmatches d1
      where flag = @flag
      and not exists (
          select max(id) id
          from dmf_product_match_unmatches  d2
          group by hid, flag
          having d1.id = max(d2.id)       
      )
      

      【讨论】:

        猜你喜欢
        • 2017-01-25
        • 1970-01-01
        • 2020-01-22
        • 1970-01-01
        • 2017-10-31
        • 1970-01-01
        • 2014-07-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多