【问题标题】:A query to delete duplicates with GROUP BY使用 GROUP BY 删除重复项的查询
【发布时间】:2013-10-09 10:04:17
【问题描述】:
id_specific_price    id_product  
-------------------------------
            1                2  
            2                2  
            3                2  
            4                3  
            5                3  
            6                3  
            7                3

需要删除重复的,预期的结果:

id_specific_price    id_product  
-------------------------------
            3                2  
            7                3

SELECT * 
  FROM ps_specific_price 
 WHERE id_specific_price NOT IN 
 (SELECT MAX(id_specific_price) 
    FROM ps_specific_price 
   GROUP BY id_product) 

有效但

DELETE FROM ps_specific_price 
 WHERE id_specific_price NOT IN 
(SELECT MAX(id_specific_price) 
   FROM ps_specific_price 
  GROUP BY id_product)

没有。有很多例子可以解决这个问题,但由于某种原因我无法适应它。我相信它是 GROUP BY。例如:

DELETE FROM ps_specific_price 
 WHERE id_specific_price NOT IN
 (SELECT MAX(p.id_specific_price) 
    FROM (SELECT * FROM ps_specific_price ) as p)
   GROUP BY id_product

我哪里出错了?

【问题讨论】:

  • 您不应在子查询中使用要删除的表。您应该使用带有游标的存储过程来归档此目标。
  • 存储过程是魔鬼的杰作。如果它不能在 SQL 中解决(它可能可以,但可能是特定于供应商的),我建议在应用程序级别(从 Java 或 PHP 等)进行 - 选择 ...;从...中删除 id_specific_price in (...)
  • @CedricSimon Quoi?您的建议(可能)仅对 mysql 有效,它不喜欢在同一语句中读取已删除或更新的表。 (除非阅读参考做了一些聚合,IIRC)
  • 这些不是重复的行,您正在删除基于比这更微妙的东西。您要求从按第二个 id 列分组的集合中删除除一行(一列中具有最高 id 的行)之外的所有行。

标签: mysql sql duplicates


【解决方案1】:

如果您正在寻找 MySQL 的解决方案,那么您可以使用正确的 multi table DELETE 语法以及像这样的 JOIN

DELETE p
  FROM ps_specific_price p JOIN
(
  SELECT id_product, MAX(id_specific_price) id_specific_price
    FROM ps_specific_price
   GROUP BY id_product
) d 
   ON p.id_product = d.id_product
  AND p.id_specific_price <> d.id_specific_price;

结果:

| ID_SPECIFIC_PRICE | ID_产品 | |-------|------------| | 3 | 2 | | 7 | 3 |

这里是SQLFiddle演示

【讨论】:

    【解决方案2】:

    试试这个:

    CREATE TABLE ps_specific_price (
      id_specific_price NUMBER,
      id_product NUMBER
    );
    
    INSERT INTO ps_specific_price (id_specific_price, id_product) VALUES (1, 2);
    INSERT INTO ps_specific_price (id_specific_price, id_product) VALUES (2, 2);
    INSERT INTO ps_specific_price (id_specific_price, id_product) VALUES (3, 2);
    INSERT INTO ps_specific_price (id_specific_price, id_product) VALUES (4, 3);
    INSERT INTO ps_specific_price (id_specific_price, id_product) VALUES (5, 3);
    INSERT INTO ps_specific_price (id_specific_price, id_product) VALUES (6, 3);
    INSERT INTO ps_specific_price (id_specific_price, id_product) VALUES (7, 3);
    
    COMMIT;
    
    DELETE FROM ps_specific_price ps
      WHERE ps.id_specific_price NOT IN (
        SELECT MAX(id_specific_price)
          FROM ps_specific_price ps_in
        WHERE ps_in.id_product = ps.id_product
        );
    
    SELECT * FROM ps_specific_price;
    
    ID_SPECIFIC_PRICE      ID_PRODUCT             
    ---------------------- ---------------------- 
    3                      2                      
    7                      3                      
    

    您必须将内部查询中的表与外部查询中的表连接起来。

    我正在使用 Oracle 11g R2。我在 SQLFiddle 上检查了这一点,我的 DELETE 语句对 MySQL 无效 - 没有安装那个,也没有太多经验,但你没有说你使用的是什么数据库。

    【讨论】:

    • 谢谢。我忘了说有几千行,这些只是前7行。所以我需要先找到重复项,然后删除它们
    • 是的,但是无论有多少子查询,您都在使用子查询“寻找”它们。请告诉我们您使用的是什么数据库。另外,你应该检查这个链接:stackoverflow.com/questions/18932/…
    【解决方案3】:

    也许你想试试:

    DELETE FROM ps_specific_price WHERE (id_product,id_specific_price) NOT IN (SELECT id_product,MAX(id_specific_price) FROM ps_specific_price GROUP BY id_product);

    我在我的 Teradata 数据库上尝试过这个,它可以工作。

    在您之前的查询中,我看到您唯一遗漏的是映射 id_product 和它的最高价格 带删除集。在删除之前删除不会知道它必须匹配 pid 和 price。

    希望这会有所帮助。

    【讨论】:

    • 谢谢。它不适用于我的 MySQL 数据库。什么是 Teradata 数据库?
    • 它是一个数据库。如果它在 My Sql 上,您可以使用外部删除表中的 id_product 在子查询中加入 id_product。
    • @popkutt:您没有提到 mysql(在对正在更新或删除的表的引用中,这是 非常受限)
    • DELETE FROM ps_specific_price outT WHERE id_specific_price NOT IN (SELECT MAX(Subq.id_specific_price) FROM ps_specific_price subq WHERE outT.id_product=subq.id_product);希望这能澄清。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多