代码之家  ›  专栏  ›  技术社区  ›  homework

正在删除SQL中的重复字段项

  •  2
  • homework  · 技术社区  · 15 年前

    我能从某个表中删除所有重复的条目吗( users )?这是我所拥有的条目类型的示例。我得说桌子 用户 由3个字段组成, ID , user pass .

    mysql_query("DELETE FROM users WHERE ???") or die(mysql_error());
    
    randomtest
    randomtest
    randomtest
    nextfile
    baby
    randomtest
    dog
    anothertest
    randomtest
    baby
    nextfile
    dog
    anothertest
    randomtest
    randomtest
    

    我想找到重复的条目,然后 删除所有重复项,并保留一个 .

    13 回复  |  直到 8 年前
        1
  •  4
  •   Sergi    15 年前

    您只能用一个查询来解决它。

    如果您的表具有以下结构:

    CREATE TABLE  `users` (
      `id` int(10) unsigned NOT NULL auto_increment,
      `username` varchar(45) NOT NULL,
      PRIMARY KEY  (`id`)
    ) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=latin1;
    

    您可以这样做(这将删除基于用户名的所有重复用户,其ID大于该用户名的较小ID):

    DELETE users
      FROM users INNER JOIN
      (SELECT MIN(id) as id, username FROM users GROUP BY username) AS t
      ON users.username = t.username AND users.id > t.id
    

    它起作用了,我已经用类似的方法删除了重复项。

        2
  •  5
  •   Ferenc Deak    15 年前

    您可以使用三个SQL执行此操作:

    create table tmp as select distinct name from users;
    drop table users;
    alter table tmp rename users;
    
        3
  •  1
  •   cjk    15 年前

    此删除脚本(SQL Server语法)应该可以工作:

    DELETE FROM Users
    WHERE ID NOT IN (
        SELECT MIN(ID)
        FROM Users
        GROUP BY User
    )
    
        4
  •  1
  •   Emil Ivanov    15 年前

    我假设您具有如下结构:

    users
    -----------------
    | id | username |
    -----------------
    |  1 | joe      |
    |  2 | bob      |
    |  3 | jane     |
    |  4 | bob      |
    |  5 | bob      |
    |  6 | jane     |
    -----------------
    

    由于MySQL不能在使用删除的目标表的删除查询中使用sub-select,因此需要对temporary执行magic操作。

    CREATE TEMPORARY TABLE IF NOT EXISTS users_to_delete (id INTEGER);
    
    INSERT INTO users_to_delete (id)
        SELECT MIN(u1.id) as id
        FROM users u1
        INNER JOIN users u2 ON u1.username = u2.username
        GROUP BY u1.username;
    
    DELETE FROM users WHERE id NOT IN (SELECT id FROM users_to_delete);
    

    我知道查询有点复杂,但它可以完成工作,即使用户表有两列以上。

        5
  •  1
  •   badbod99    15 年前

    您需要对如何使用表中的数据稍微谨慎一点。如果这确实是一个用户表,那么可能还有其他表fk指向id列。在这种情况下,您需要更新这些表以使用您选择要保留的ID。

    如果它只是一个独立的表(没有表引用它)

    CREATE TEMPORARY TABLE Tmp (ID int);
    INSERT INTO Tmp SELECT ID FROM USERS GROUP BY User;
    DELETE FROM Users WHERE ID NOT IN (SELECT ID FROM Tmp);
    

    从其他表链接的用户表

    创建临时表,包括一个链接表,其中保存了其他表应该引用的所有旧ID和相应的新ID。

    CREATE TEMPORARY TABLE Keep (ID int, User varchar(45));
    CREATE TEMPORARY TABLE Remove (OldID int, NewID int);
    INSERT INTO Keep SELECT ID, User FROM USERS GROUP BY User;
    INSERT INTO Remove SELECT u1.ID, u2.ID FROM Users u1 INNER JOIN Keep u2 ON u2.User = u1.User WHERE u1.ID NOT IN (SELECT ID FROM Users GROUP BY User);
    

    浏览所有引用用户表的表,并更新其FK列(可能称为userid)以指向您选择的新唯一ID,如…

    UPDATE MYTABLE t INNER JOIN Remove r ON t.UserID = r.OldID
    SET t.UserID = r.NewID;
    

    最后返回到用户表并删除不再引用的重复项:

    DELETE FROM Users WHERE ID NOT IN (SELECT ID FROM Keep);
    

    清理这些TMP表:

    DROP TABLE KEEP;
    DROP TABLE REMOVE;
    
        6
  •  0
  •   Paul Lammertsma    15 年前

    一个非常简单的解决方案是 UNIQUE 希望具有唯一值的表列的索引。请注意,随后不能插入同一个键两次。

    编辑:我错了,我没有读到最后一行:“我想找到重复的条目”。

        7
  •  0
  •   dotty    15 年前

    我会得到所有的结果,将它们放入一个ID和值数组中。使用php函数计算重复数据,记录数组中的所有ID,并使用这些值删除记录。

        8
  •  0
  •   Tomas    15 年前

    我不知道你的数据库模式,但最简单的解决方案似乎是 SELECT DISTINCT 在该表上,将结果保存在变量(即数组)中,删除表中的所有记录,然后重新插入返回列表 选择不同 以前。

        9
  •  0
  •   Paul Lammertsma    15 年前

    临时桌是一个很好的解决方案,但我想提供一个 SELECT 从表中提取重复行作为替代项的查询:

    SELECT * FROM `users` LEFT JOIN (
            SELECT `name`, COUNT(`name`) AS `count`
            FROM `users` GROUP BY `name`
        ) AS `grouped`
        WHERE `grouped`.`name` = `users`.`name`
        AND `grouped`.`count`>1
    
        10
  •  0
  •   RPL    15 年前

    根据表结构选择3列,并根据需要应用条件。

    从用户中选择user.userid、user.username user.password作为用户 按user.userid、user.username分组 具有(count(user.username)>1));

        11
  •  0
  •   homework    15 年前

    上面和/或下面的每一个答案对我都不起作用,因此我决定自己写一个小剧本。这不是最好的,但能完成任务。
    评论贯穿始终,但这个脚本是为我的需要而定制的,我希望这个想法能帮助您。

    我基本上将数据库内容写入一个名为temp文件的temp文件,将函数应用于被调用的文件以删除重复项,截断表,然后立即将数据输入到SQL中。听起来很不错,我知道。

    如果你对什么感到困惑 $setprofile 也就是说,这是一个在登录到我的脚本(建立配置文件)时创建的会话,在注销时清除。


    <?php
    // session and includes, you know the drill.
    session_start();
    include_once('connect/config.php');
    
    // create a temp file with session id and current date
    $datefile =  date("m-j-Y");
    $file = "temp/$setprofile-$datefile.txt";
    
    $f = fopen($file, 'w'); // Open in write mode
    
    // call the user and pass via SQL and write them to $file
    $sql = mysql_query("SELECT * FROM _$setprofile ORDER BY user DESC");
    while($row = mysql_fetch_array($sql))
    {
    $user = $row['user'];
    $pass = $row['pass'];
    
    $accounts = "$user:$pass "; // the white space right here is important, it defines the separator for the dupe check function
    fwrite($f, $accounts);
    
    }
    fclose($f);
    
    
    // **** Dupe Function **** //
    
    // removes duplicate substrings between the seperator
    function uniqueStrs($seperator, $str) {
    // convert string to an array using ' ' as the seperator
    $str_arr = explode($seperator, $str);
    // remove duplicate array values
    $result = array_unique($str_arr);
    // convert array back to string, using ' ' to glue it back
    $unique_str = implode(' ', $result);
    // return the unique string
    return $unique_str;
    }
    
    // **** END Dupe Function **** //
    
    
    // call the list we made earlier, so we can use the function above to remove dupes
    $str = file_get_contents($file);
    // seperator
    $seperator = ' ';
    // use the function to save a unique string
    $new_str = uniqueStrs($seperator, $str);
    
    
    
    // empty the table
    mysql_query("TRUNCATE TABLE _$setprofile") or die(mysql_error());
    
    // prep for SQL by replacing test:test with ('test','test'), etc.
    // this isn't a sufficient way of converting, as  i said, it works for me.
    $patterns = array("/([^\s:]+):([^\s:]+)/", "/\s++\(/");
    $replacements = array("('$1', '$2')", ", (");
    
    
    // insert the values into your table, and presto! no more dupes.
    $sql = 'INSERT INTO `_'.$setprofile.'` (`user`, `pass`) VALUES ' . preg_replace($patterns, $replacements, $new_str) . ';';
    $product = mysql_query($sql) or die(mysql_error()); // put $new_str here so it will replace new list with SQL formatting
    
    // if all goes well.... OR wrong? :)
    if($product){ echo "Completed!";
    } else {
    echo "Failed!";
    }
    
    unlink($file); // delete the temp file/list we made earlier
    ?>
    
        12
  •  0
  •   Brock Adams    13 年前

    这将起作用:

    create table tmp like users;
    insert into tmp select distinct name from users;
    drop table users;
    alter table tmp rename users;
    
        13
  •  -1
  •   Kristen    15 年前

    如果表上有唯一的ID/主键,则:

    DELETE FROM MyTable AS T1
    WHERE MyID <
    (
        SELECT MAX(MyID)
        FROM MyTable AS T2
        WHERE     T2.Col1 = T1.Col1
              AND T2.Col2 = T1.Col2
              ... repeat for all columns to consider duplicates ...
    )
    

    如果没有唯一键,请将所有不同的值选择到临时表中,删除所有原始行,然后从临时表中复制回来-但如果有引用此表的外键,则会出现问题。