J'ai une table de base de données MySQL avec deux colonnes qui m'intéressent. Individuellement, ils peuvent avoir des doublons, mais ils ne doivent jamais avoir un duplicata des DEUX ayant la même valeur.
stone_id
peut avoir des doublons tant que pour chaque upsharge
le titre est différent et inversement. Mais disons par exemple stone_id
= 412 et upcharge_title
= "saphir", cette combinaison ne doit apparaître qu'une seule fois.
C'est acceptable:
stone_id = 412 upcharge_title = "sapphire"
stone_id = 412 upcharge_title = "Ruby"
Ce n'est pas ok:
stone_id = 412 upcharge_title = "sapphire"
stone_id = 412 upcharge_title = "sapphire"
Existe-t-il une requête permettant de trouver des doublons dans les deux champs? Et si possible existe-t-il un moyen de configurer ma base de données pour ne pas permettre cela?
J'utilise MySQL version 4.1.22
Vous devez configurer une clé composite entre les deux champs. Cela nécessitera un identifiant unique stone_id et upcharge_title pour chaque ligne.
En ce qui concerne la recherche des doublons existants, essayez ceci:
select stone_id,
upcharge_title,
count(*)
from your_table
group by stone_id,
upcharge_title
having count(*) > 1
J'ai trouvé utile d'ajouter un index unqiue en utilisant un "ALTER IGNORE" qui supprime les doublons et applique des enregistrements uniques qui sonnent comme vous le souhaitez. Donc, la syntaxe serait la suivante:
ALTER IGNORE TABLE `table` ADD UNIQUE INDEX(`id`, `another_id`, `one_more_id`);
Cela ajoute effectivement la contrainte unique, ce qui signifie que vous ne créerez jamais d'enregistrements en double et que IGNORE supprimera les doublons existants.
Vous pouvez en savoir plus sur ALTER IGNORE ici: http://mediakey.dk/~cc/mysql-remove-duplicate-entries/
Mise à jour: @Inquisitive m'a informé que cela pourrait échouer dans les versions de MySql> 5.5:
Il échoue sur MySQL> 5.5 et sur la table InnoDB, ainsi que dans Percona en raison de la fonctionnalité de création rapide d’InnoDB [ http://bugs.mysql.com/bug.php?id=40344] . Dans ce cas, lancez
set session old_alter_table=1
puis la commande ci-dessus fonctionnera correctement
Mise à jour - ALTER IGNORE
Supprimé dans 5.7
De la docs
Depuis MySQL 5.6.17, la clause IGNORE est obsolète et son utilisation génère un avertissement. IGNORE est supprimé de MySQL 5.7.
Un des devs de MySQL donne deux alternatives :
INSERT IGNORE
, ex:CREATE TABLE duplicate_row_table LIKE regular_row_table;
ALTER TABLE duplicate_row_table ADD UNIQUE INDEX (id, another_id);
INSERT IGNORE INTO duplicate_row_table SELECT * FROM regular_row_table;
DROP TABLE regular_row_table;
RENAME TABLE duplicate_row_table TO regular_row_table;
Mais selon la taille de votre table, cela peut ne pas être pratique
Vous pouvez trouver des doublons comme celui-ci ..
Select
stone_id, upcharge_title, count(*)
from
particulartable
group by
stone_id, upcharge_title
having
count(*) > 1
Pour trouver les doublons:
select stone_id, upcharge_title from tablename group by stone_id, upcharge_title having count(*)>1
Pour éviter cela à l'avenir, créez une clé unique composite sur ces deux champs.
Incidemment, une contrainte unique composite sur la table empêcherait cela de se produire en premier lieu.
ALTER TABLE table
ADD UNIQUE(stone_id, charge_title)
(Ceci est valide T-SQL. Pas sûr de MySQL.)
ceci SO post m'a aidé, mais je voulais aussi savoir comment supprimer et conserver l'une des lignes ... voici une PHP solution pour supprimer le duplicata lignes et en garder une (dans mon cas, il n'y avait que 2 colonnes et il est dans une fonction pour effacer les associations de catégorie en double)
$dupes = $db->query('select *, count(*) as NUM_DUPES from PRODUCT_CATEGORY_PRODUCT group by fkPRODUCT_CATEGORY_ID, fkPRODUCT_ID having count(*) > 1');
if (!is_array($dupes))
return true;
foreach ($dupes as $dupe) {
$db->query('delete from PRODUCT_CATEGORY_PRODUCT where fkPRODUCT_ID = ' . $dupe['fkPRODUCT_ID'] . ' and fkPRODUCT_CATEGORY_ID = ' . $dupe['fkPRODUCT_CATEGORY_ID'] . ' limit ' . ($dupe['NUM_DUPES'] - 1);
}
la (limite NUM_DUPES - 1) est ce qui préserve la seule ligne ...
merci a tous