AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 5859
Accepted
Gary Lindahl
Gary Lindahl
Asked: 2011-09-17 05:22:13 +0800 CST2011-09-17 05:22:13 +0800 CST 2011-09-17 05:22:13 +0800 CST

Excluindo todas as duplicatas

  • 772

Estou tentando excluir todas as duplicatas, mas mantendo apenas um único registro (ID mais curto). A consulta a seguir exclui as duplicatas, mas leva muitas iterações para excluir todas as cópias e manter as originais.

DELETE FROM emailTable WHERE id IN (
 SELECT * FROM (
    SELECT id FROM emailTable GROUP BY email HAVING ( COUNT(email) > 1 )
 ) AS q
)

É MySQL.

DDL

CREATE TABLE `emailTable` (
 `id` mediumint(9) NOT NULL auto_increment,
 `email` varchar(200) NOT NULL default '',
 PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=298872 DEFAULT CHARSET=latin1
mysql delete
  • 3 3 respostas
  • 6803 Views

3 respostas

  • Voted
  1. Best Answer
    Derek Downey
    2011-09-17T05:46:22+08:002011-09-17T05:46:22+08:00

    Tente isto:

    DELETE FROM emailTable WHERE NOT EXISTS (
     SELECT * FROM (
        SELECT MIN(id) minID FROM emailTable    
        GROUP BY email HAVING COUNT(*) > 0
      ) AS q
      WHERE minID=id
    )
    

    O acima funcionou para o meu teste de 50 e-mails (5 e-mails diferentes duplicados 10 vezes).

    Pode ser necessário adicionar um índice na coluna 'email':

    ALTER TABLE emailTable ADD INDEX ind_email (email);
    

    Pode ser um pouco lento para 250.000 linhas. Foi lento para mim em uma tabela que tinha 1,5 milhão de linhas (devidamente indexadas), e foi assim que criei esta estratégia:

    /* CREATE MEMORY TABLE TO HOUSE IDs of the MIN */
    CREATE TABLE email_min (minID INT, PRIMARY KEY(minID)) ENGINE=Memory;
    
    /* INSERT THE MINIMUM IDs */
    INSERT INTO email_min SELECT id FROM email
        GROUP BY email HAVING MIN(id);
    
    /* MAKE SURE YOU HAVE RIGHT INFO */
    SELECT * FROM email 
     WHERE NOT EXISTS (SELECT * FROM email_min WHERE minID=id)
    
    /* DELETE FROM EMAIL */
    DELETE FROM email 
     WHERE NOT EXISTS (SELECT * FROM email_min WHERE minID=id)
    
    /* IF ALL IS WELL, DROP MEMORY TABLE */
    DROP TABLE email_min;
    

    O benefício da tabela de memória é que há um índice usado (chave primária no minID) que acelera o processo em uma tabela temporária normal.

    • 8
  2. RolandoMySQLDBA
    2011-09-17T08:01:05+08:002011-09-17T08:01:05+08:00

    Aqui está um processo de exclusão mais simplificado:

    CREATE TABLE emailUnique LIKE emailTable;
    ALTER TABLE emailUnique ADD UNIQUE INDEX (email);
    INSERT IGNORE INTO emailUnique SELECT * FROM emailTable;
    SELECT * FROM emailUnique;
    ALTER TABLE emailTable  RENAME emailTable_old;
    ALTER TABLE emailUnique RENAME emailTable;
    DROP TABLE emailTable_old;
    

    Aqui estão alguns dados de amostra:

    use test
    DROP TABLE IF EXISTS emailTable;
    CREATE TABLE `emailTable` (
     `id` mediumint(9) NOT NULL auto_increment,
     `email` varchar(200) NOT NULL default '',
     PRIMARY KEY  (`id`)
    ) ENGINE=MyISAM;
    INSERT INTO emailTable (email) VALUES
    ('[email protected]'),
    ('[email protected]'),
    ('[email protected]'),
    ('[email protected]'),
    ('[email protected]'),
    ('[email protected]'),
    ('[email protected]'),
    ('[email protected]'),
    ('[email protected]'),
    ('[email protected]'),
    ('[email protected]'),
    ('[email protected]'),
    ('[email protected]'),
    ('[email protected]'),
    ('[email protected]');
    SELECT * FROM emailTable;
    

    Eu os corri. Aqui estão os resultados:

    mysql> use test
    Database changed
    mysql> DROP TABLE IF EXISTS emailTable;
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> CREATE TABLE `emailTable` (
        ->  `id` mediumint(9) NOT NULL auto_increment,
        ->  `email` varchar(200) NOT NULL default '',
        ->  PRIMARY KEY  (`id`)
        -> ) ENGINE=MyISAM;
    Query OK, 0 rows affected (0.05 sec)
    
    mysql> INSERT INTO emailTable (email) VALUES
        -> ('[email protected]'),
        -> ('[email protected]'),
        -> ('[email protected]'),
        -> ('[email protected]'),
        -> ('[email protected]'),
    ('[email protected]');
    SELECT * FROM emailTable;
        -> ('[email protected]'),
        -> ('[email protected]'),
        -> ('[email protected]'),
        -> ('[email protected]'),
        -> ('[email protected]'),
        -> ('[email protected]'),
        -> ('[email protected]'),
        -> ('[email protected]'),
        -> ('[email protected]'),
        -> ('[email protected]');
    Query OK, 15 rows affected (0.00 sec)
    Records: 15  Duplicates: 0  Warnings: 0
    
    mysql> SELECT * FROM emailTable;
    +----+----------------------------+
    | id | email                      |
    +----+----------------------------+
    |  1 | [email protected]         |
    |  2 | [email protected]         |
    |  3 | [email protected]         |
    |  4 | [email protected]         |
    |  5 | [email protected]   |
    |  6 | [email protected]   |
    |  7 | [email protected]   |
    |  8 | [email protected]              |
    |  9 | [email protected]              |
    | 10 | [email protected]              |
    | 11 | [email protected]   |
    | 12 | [email protected]   |
    | 13 | [email protected] |
    | 14 | [email protected] |
    | 15 | [email protected] |
    +----+----------------------------+
    15 rows in set (0.00 sec)
    
    mysql> CREATE TABLE emailUnique LIKE emailTable;
    Query OK, 0 rows affected (0.04 sec)
    
    mysql> ALTER TABLE emailUnique ADD UNIQUE INDEX (email);
    Query OK, 0 rows affected (0.06 sec)
    Records: 0  Duplicates: 0  Warnings: 0
    
    mysql> INSERT IGNORE INTO emailUnique SELECT * FROM emailTable;
    Query OK, 4 rows affected (0.01 sec)
    Records: 15  Duplicates: 11  Warnings: 0
    
    mysql> SELECT * FROM emailUnique;
    +----+----------------------------+
    | id | email                      |
    +----+----------------------------+
    |  1 | [email protected]         |
    |  5 | [email protected]   |
    |  8 | [email protected]              |
    | 13 | [email protected] |
    +----+----------------------------+
    4 rows in set (0.00 sec)
    
    mysql> ALTER TABLE emailTable  RENAME emailTable_old;
    Query OK, 0 rows affected (0.03 sec)
    
    mysql> ALTER TABLE emailUnique RENAME emailTable;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> DROP TABLE emailTable_old;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql>
    

    Conforme mostrado, a emailTable conterá a primeira ocorrência de cada endereço de e-mail e o ID original correspondente. Para este exemplo:

    • Os IDs 1-4 têm [email protected], mas apenas 1 foi preservado.
    • IDs 5-7,11,12 têm [email protected], mas apenas 5 foi preservado.
    • IDs 8-10 têm [email protected], mas apenas 8 foram preservados.
    • IDs 13-15 têm [email protected], mas apenas 13 foi preservado.

    CAVEAT: Respondi a uma pergunta semelhante a esta sobre exclusão de tabela por meio de uma abordagem de tabela temporária .

    De uma chance !!!

    • 4
  3. Delux
    2011-09-17T06:18:28+08:002011-09-17T06:18:28+08:00

    Aqui está uma solução Itzik rápida e real. Isso funcionará no SQL 2005 e superior.

    WITH Dups AS
    (
      SELECT *,
        ROW_NUMBER()
          OVER(PARTITION BY email ORDER BY id) AS rn
      FROM dbo.emailTable
    )
    DELETE FROM Dups
    WHERE rn > 1;
    
    • 1

relate perguntas

  • Existem ferramentas de benchmarking do MySQL? [fechado]

  • Onde posso encontrar o log lento do mysql?

  • Como posso otimizar um mysqldump de um banco de dados grande?

  • Quando é o momento certo para usar o MariaDB em vez do MySQL e por quê?

  • Como um grupo pode rastrear alterações no esquema do banco de dados?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Como você mostra o SQL em execução em um banco de dados Oracle?

    • 2 respostas
  • Marko Smith

    Como selecionar a primeira linha de cada grupo?

    • 6 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Posso ver Consultas Históricas executadas em um banco de dados SQL Server?

    • 6 respostas
  • Marko Smith

    Como uso currval() no PostgreSQL para obter o último id inserido?

    • 10 respostas
  • Marko Smith

    Como executar o psql no Mac OS X?

    • 11 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Marko Smith

    Passando parâmetros de array para um procedimento armazenado

    • 12 respostas
  • Martin Hope
    Manuel Leduc Restrição exclusiva de várias colunas do PostgreSQL e valores NULL 2011-12-28 01:10:21 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Stuart Blackler Quando uma chave primária deve ser declarada sem cluster? 2011-11-11 13:31:59 +0800 CST
  • Martin Hope
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    BrunoLM Guid vs INT - Qual é melhor como chave primária? 2011-01-05 23:46:34 +0800 CST
  • Martin Hope
    bernd_k Quando devo usar uma restrição exclusiva em vez de um índice exclusivo? 2011-01-05 02:32:27 +0800 CST
  • Martin Hope
    Patrick Como posso otimizar um mysqldump de um banco de dados grande? 2011-01-04 13:13:48 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve