Page 1 sur 1

requete imbriquée

Posté : 11 mai 2009, 15:33
par jobrider
salut à tous,
je cherche à supprimer tous les email de la table a qui sont identiques à la table b

est-ce que la requête suivante est correct ? (j'ai pas testé encore car je traite + de 50000 email et le traitement va être assez long)

DELETE FROM tablea WHERE email IN (SELECT email FROM tableb);

merci pour votre aide

Posté : 11 mai 2009, 16:13
par albat
Modération :
Afin d'obtenir plus de réponses, le sujet est déplacé dans le forum "SQL & Bases de données".

Merci de prendre le temps de lire les règlements
ainsi que l'intitulé de chaque forum avant de poster un nouveau sujet.

Posté : 11 mai 2009, 16:30
par sadeq
DELETE FROM tablea WHERE email IN (SELECT email FROM tableb);
Oui, cette requête fait l'affaire.

Posté : 11 mai 2009, 18:10
par jobrider
merci
j'ai un souci j'ai 35000 email dans tablea et 66000 email dans la tableb.. le script tourne pendant + de 10 minutes et forcément j'abandonne.. qu'est ce que je peux faire..
attendre encore? j'ai essayé de poser un LIMIT 20 et rien n'y fait le script tourne en rond..

$result_insert=mysql_query("DELETE FROM tableb WHERE email IN (SELECT email FROM tableb) LIMIT 20");

Posté : 11 mai 2009, 20:53
par albat
Salut Pierre-Alain, ;)

La requête que tu utilises est correcte syntaxiquement,
mais au niveau de l'optimisation, comme tu l'as remarqué, c'est épouvantable.

En général, lorsque l'on se retrouve dans une situation de ce type,
c'est imputable à un défaut de modélisation de la base de données.
L'idéal est alors de reprendre son modèle et de le corriger.
Mais ce n'est pas toujours possible.

Je te propose l'astuce suivante,
mais j'ignore si elle est applicable dans ton cas.

1. Fusionner les tables A et B en une seule table.
2. Supprimer les doublons de cette table.

Posté : 12 mai 2009, 09:50
par jobrider
super,
merci albat
je travaille avec de tables test sur phpmyadmin donc je peux manipuler comme je veux.
Les 2 tables sont déjà dédoublonnées, par contre elles ce n'est pas le cas, et c'ets ce que je souhaite faire. Les tables ont chacune les champs suivants :
id_email int(10)
email varchar(200) latin1_swedish_ci

y'a pourtant pas beaucoup de champs..
Je vais essayer avec un select plutot qu'un delete.

[Note : ce message a été posté de manière anonyme avant d'être réattribué à son auteur]

Posté : 12 mai 2009, 12:37
par sadeq
Déjà pour optimiser on peut modifier la requête:

Code : Tout sélectionner

DELETE FROM tablea WHERE email IN (SELECT email FROM tableb)
En la récrivant comme ça:

Code : Tout sélectionner

DELETE FROM tablea WHERE id_email IN (SELECT DISTINCT id_email FROM tableb)
Pour utiliser id_email qui est un index numérique au lieu du champ "email" qui est un texte, on gagne du temps quant à la recherche effectuée par WHERE et IN, car la recherche d'un index numérique est plus rapide que celle d'un index de type texte.
Et on peut ajouter une limite pour le nombre de suppression, mais le mot LIMIT doit être à la fin de la commande DELETE:

Code : Tout sélectionner

DELETE FROM tablea WHERE id_email IN (SELECT DISTINCT id_email FROM tableb) LIMIT 20
Ici, seules 20 suppressions max sont autorisées.

En suite, on peut abandonner l'opérateur IN qui oblige la requête de chercher dans un ensemble. Ce qui oblige le moteur de requête à construire d'abord l'ensemble (SELECT ....) avant de faire la recherche IN.
Pour cela, on remplace IN par une jointure naturelle (relation) : JOIN entre les 2 tables, ce qui donne la requête suivante:

Code : Tout sélectionner

DELETE A.* FROM tablea A JOIN tableb B ON A.id_email = B.id_email
La spécification de A.* dans la commande DELETE est obligatoire dans notre cas car elle désigne la table où sera effectuée la suppression puisque dans le FROM on utilise au moins 2 tables liées A et B.
Remarque: Dans cette solution de jointure, le DELETE ne supporte pas le mot LIMIT dans une requête multi-tables.

Posté : 12 mai 2009, 19:06
par jobrider
salut,
je savais qu'on pouvais faire un JOIN avec un delete ?!
mais j'ai essayé : ça me supprime tout sur tablea en mois d'une seconde chorno, pour le coup c'est super otpimisé mais c'est pas le résultat escompté..
:roll:

[Note : ce message a été posté de manière anonyme avant d'être réattribué à son auteur]

Posté : 12 mai 2009, 22:07
par sadeq
Peux-tu donner la requête que tu as écrit ?

Posté : 13 mai 2009, 00:44
par Nagol
set_time_limit aussi pourrais t'aider tu cherches à nettoyer une table, ca n'a pas besoin d'etre optimisé si ce n'est pas une action utilisateur.

Posté : 13 mai 2009, 10:10
par jobrider
salut,

voici la requete que j'ai testé sans succès..
$result_insert=mysql_query("DELETE A.* FROM matable A JOIN matable2 B ON A.id_email = B.id_email");

j'ai laissé tourné la1ere requete cette nuit et c'est bon finallement, j'aurai du mettre un compteur pour moi le temps necessaire au final..

merci