删除SQL中的重复字段条目

时间:2009-11-13 09:07:39

标签: php sql duplicates

无论如何我可以删除某个表(users)中的所有重复条目吗?这是我所拥有的条目类型的示例。我必须说表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 个答案:

答案 0 :(得分:5)

您可以使用三个平方码来完成:

create table tmp as select distinct name from users;
drop table users;
alter table tmp rename users;

答案 1 :(得分:4)

您只需一个查询即可解决此问题。

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

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 :(得分:1)

此删除脚本(SQL Server语法)应该有效:

DELETE FROM Users
WHERE ID NOT IN (
    SELECT MIN(ID)
    FROM Users
    GROUP BY User
)

答案 3 :(得分:1)

我假设您有如下结构:

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

由于MySQL无法在使用删除目标表的删除查询中使用子选择,因此需要使用临时魔术。

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);

我知道查询有点毛茸茸,但即使用户表的列数超过2列,也能正常工作。

答案 4 :(得分:1)

您需要小心如何使用表中的数据。如果这确实是一个用户表,则可能有其他表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);

浏览任何引用您的users表的表并更新其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;

答案 5 :(得分:0)

一个非常简单的解决方案是在表格的列上设置一个UNIQUE索引,以获得唯一值。请注意,您随后无法两次插入相同的密钥。

编辑:我的错误,我没有读到最后一行:“我希望能够找到重复的条目”。

答案 6 :(得分:0)

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

答案 7 :(得分:0)

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

答案 8 :(得分:0)

临时表是一个很好的解决方案,但我想提供一个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

答案 9 :(得分:0)

这将有效:

create table tmp like users;
insert into tmp select distinct name from users;
drop table users;
alter table tmp rename users;

答案 10 :(得分:0)

根据您的表格结构选择3列,并根据您的要求应用条件。

SELECT user.userId,user.username user.password FROM user As user GROUP BY user.userId,user.username HAVING(COUNT(user.username)> 1));

答案 11 :(得分:0)

上面和/或下面的每个答案对我都不起作用,因此我决定编写自己的小脚本。这不是最好的,但它完成了工作 评论包含在内,但是这个脚本是根据我的需求定制的,我希望这个想法对你有帮助。

我基本上将数据库内容写入临时文件,称为临时文件,将函数应用于被调用文件以删除重复项,截断表,然后将数据直接输入到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 :(得分:-1)

如果桌面上有唯一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 ...
)

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