【问题标题】:How can I optimise this SQL query to delete every second duplicate row?如何优化此 SQL 查询以删除每隔一个重复的行?
【发布时间】:2019-03-27 00:48:04
【问题描述】:

我只需要保留一个重复值的行,即删除不是具有重复值的“第一”行的每一行。

我有一个名为 ART_NEW 的表格:

PHARMACODE | GTIN | {Other stuff}
111          1234   ...
  • PHARMACODE 是主键(整数)
  • GTIN 是另一个整数,据说是唯一的,但有时会发生冲突。

此表的数据源正准备从 PHARMACODE 转换为 GTIN 作为主键,但此转换尚未完成。我以任何方式控制源。

要在某些应用程序中使用 GTIN 作为 PK,我需要删除所有重复 GTIN 的行(所有具有相同 GTIN 的行描述相同的产品,其描述略有不同,所以它删除哪一行和不删除哪一行都没有关系,只要我最终只有一行用于特定 GTIN 值)。

以下查询完全符合我的需要,但速度非常慢(在 350'000 条记录中执行时间超过 1 分钟,其中 120 行具有重复的 GTIN 值):

DELETE *
FROM ART_NEW
WHERE ART_NEW.PHARMACODE IN 
    (SELECT PHARMACODE FROM
        (SELECT
            ART_NEW.[PHARMACODE],
            ART_NEW.GTIN,
            (SELECT Count(*)
                FROM ART_NEW As X
                WHERE X.GTIN = ART_NEW.GTIN
                    AND X.PHARMACODE <= ART_NEW.PHARMACODE) AS SeqNo
            FROM ART_NEW
            WHERE ART_NEW.[GTIN] In 
            (SELECT [GTIN] FROM [ART_NEW] As Tmp GROUP BY [GTIN] HAVING Count(*)>1)) 
        WHERE SeqNo > 1);

如何优化此代码?或者,是否有更好的方法来实现我删除每一行但具有重复 GTIN 值的每一行的目标?

【问题讨论】:

  • 在使用 DAO 的 VBA 中,循环通过排序的记录集,并且对于每条记录,存储 GTIN 并将其与前一个记录中存储的 GTIN 进行对比。如果满足规则,删除记录并继续。

标签: sql ms-access


【解决方案1】:

如果表上没有主键,这是删除重复行的简单方法。将您的 PartitionBy 设置为您认为是唯一标识符的内容,并将您的 order by 设置为您的排序顺序,使您的最顶行成为您的有效数据,并且在其下方排序的所有内容都是您要删除的无效数据。

DELETE a
FROM (
        SELECT 
           ROW_NUMBER() OVER (PARTITION BY tableUniqueid ORDER BY dateCreated DESC) AS SEQ,
           *
        FROM myTable
) a
WHERE SEQ > 1

【讨论】:

  • 遗憾的是,桌面Access没有内置ROW_NUMBERPartition函数与SQLPARTITION语句完全不同。
【解决方案2】:

看起来 PHARMACODE 是数字,应该适用于标准 SQL:

delete * from ART_NEW 
where ART_NEW.PHARMACODE  NOT IN 
(select a3.PHARMACODE from (select min(a2.PHARMACODE) as PHARMACODE, a2.GTIN from ART_NEW a2 group by a2.GTIN) a3)
;

select * from ART_NEW 
where ART_NEW.PHARMACODE  IN 
(select a3.PHARMACODE from (select min(a2.PHARMACODE) as PHARMACODE, a2.GTIN from ART_NEW a2 group by a2.GTIN) a3)
;

此外,如果您能够使用分区,请尝试使用 OVER (PARTITION BY GTIN) 使 Where for row=1。

【讨论】:

  • 您当前的代码将表格相乘,使其有效地运行超过 350,000*350,000 条记录...
  • 感谢您的解释,它确实是在增加表格!
  • 稍微调整一下,您的查询就可以工作了:按原样使用,它会选择/删除每个 GTIN 的一行,即使它不是重复的。通过运行两个顺序查询(第一个检测重复,第二个删除带有min(PHARMACODE) 的行),该过程大大加快了。感谢您为我指明正确的方向!
  • 是的,抱歉,创建第一个查询只是为了检测要删除的重复项,但没有详细说明!很高兴它有帮助
猜你喜欢
  • 1970-01-01
  • 2022-01-20
  • 1970-01-01
  • 2012-05-31
  • 2011-08-14
  • 2021-05-24
  • 1970-01-01
  • 2016-02-27
  • 1970-01-01
相关资源
最近更新 更多