SQL yinelenen alan girişlerini Çıkarma

13 Cevap php

Belirli bir tablodan tüm yinelenen girdileri silebilirsiniz yine de var mı (users)? İşte var girişlerinin türü bir örnek. Ben tablo users 3 alanları, ID , user , and pass oluşmaktadır söylemeliyim.

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

Ben yinelenen girdileri bulmak mümkün olmak istiyorum, ve sonra delete all of the duplicates, and leave one.

13 Cevap

Sadece tek bir sorgu ile çözebilir.

Tablo aşağıdaki yapıya sahipse:

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;

Eğer böyle bir şey (bu ile kullanıcı adı ve kullanıcı adı için küçük kimliği daha fazla kimliği dayalı tüm yinelenen kullanıcıları siler) yapabilirdi:

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

Bu çalışır ve zaten çiftleri silmek için benzer bir şey kullanın ettik.

Üç sqls ile yapabilirsiniz:

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

Bu silme komut dosyası (SQL Server sözdizimi) çalışması gerekir:

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

Ben aşağıdaki gibi bir yapıya sahip olduğunu varsayalım:

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

Geçici MySQL beri gerekli olan sihir yaparken en silme hedef tablo kullanır silme sorguda bir sub-select kullanamazsınız.

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

Kullanıcıların tablo fazla 2 sütun var olsa bile, ben sorgu biraz tüylü olduğunu biliyorum ama çalışır.

Eğer tablodaki verilerin nasıl kullanıldığını biraz dikkatli olmak gerekir. Bu gerçekten kullanıcıların tablo ise, kimliği sütunu işaret FKS ile olası diğer tabloları var. Bu durumda tutmak için seçtiğiniz kimliği kullanmak için bu tabloları güncellemek gerekir.

If it's just a standalone table (no table reference it)

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

Users table linked from other tables

Diğer tablolar yerine başvurmalıdır tüm eski id ve ilgili yeni kimlikleri tutan bir bağlantı tablo gibi geçici tablolar oluşturun.

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

Kullanıcıların tabloya başvuruda herhangi tabloları geçmesi ve bunu gibi, seçmiş Yeni benzersiz kimliği işaret onların FK sütunu (muhtemelen UserID denir) güncelleştirmek ...

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

Son olarak kullanıcıların tabloya geri dönmek ve artık başvurulan kaldır çiftleri:

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

Bu Tmp tabloları temizleyin:

DROP TABLE KEEP;
DROP TABLE REMOVE;

Çok basit bir çözüm benzersiz ğarametrelerin tablonun sütununda bir UNIQUE endeksi ayarlamak olacaktır. Sonradan iki kez aynı anahtarı takın unutmayın.

Düzenleme: "Ben yinelenen girdileri bulmak mümkün istiyorum:" Benim hatam, ben o son satırı okumamıştım.

Ben, bütün sonuçları almak kimlikleri ve değerleri bir dizi onları koymak istiyorsunuz. , Dupes çalışmak dizideki tüm kimlikleri oturum ve kayıtları silmek için bu değerleri kullanmak üzere bir PHP işlevini kullanın.

Ben senin db şema bilmiyorum, ama basit çözüm, SELECT DISTINCT bu tabloda yapmak bir değişken (yani dizi) sonucunu tutmak, tablodan tüm kayıtları silin ve sonra yeniden takın gibi görünüyor SELECT DISTINCT Önceden tarafından returne listesi.

Geçici tablo mükemmel bir çözümdür, ama alternatif olarak tablodaki yinelenen satırları kapmak SELECT sorgu sunmak istiyorum:

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

Tablo yapısı başı olarak 3 sütun seçin ve ihtiyaçlarına göre koşul uygulamak.

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

Every answer above and/or below didn't work for me, therefore I decided to write my own little script. It's not the best, but it gets the job done.
Comments are included throughout, but this script is customized for my needs, and I hope the idea helps you.

I basically wrote the database contents to a temp file, called the temp file, applied the function to the called file to remove the duplicates, truncated the table, and then input the data right back into the SQL. Sounds like a lot, I know.

If you're confused as to what $setprofile is, it's a session that's created upon logging into my script (to establish a profile), and is cleared upon logging out.


<?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
?>

Bu çalışacaktır:

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

Eğer masada bir Benzersiz Kimlik / Birincil anahtar varsa:

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

Bir Unique Key geçici bir tabloya tüm farklı değerleri seçin yoksa, tüm orijinal satırları silmek ve geçici tablodan geri kopyalama - ama Dışişleri Keys bu tabloya atıfta varsa, bu sorunlu olacaktır