Tavarlindar Posté 27 Janvier 2007 Posté 27 Janvier 2007 Bonjour à Tous, Voilà confronté à un problème de lenteur dans une application PHP-Mysql, je cherche à optimiser en premier lieu ma requête SQL. Le problème c'est que je n'arrive pas à pondre la requête sql adéquate. Contexte simplifié : Jai 2 tables. Une table demande et une table Contact. Un contact peut effectuer 0 ou plusieurs demandes. Un contact se caractérise par de nombreux attributs dont une adresse email. Mes deux tables sont reliées via lid_contact. Exemple : id_contact...nom..............email1 ------------------------------------------------------- 1..............TOTO............toto_AT_free.fr 2..............LEON............leon_AT_wanadoo.fr 3..............TOTO...............toto_AT_free.fr 4..............PAUL1.............paul_AT_neuf.fr 5..............NOEMIE..........nono_AT_club.fr 6..............PAUL2.............paul_AT_neuf.fr id_demande....date_demande......contact_id --------------------------------------------------------- 1...................25/01/2006.................1 2...................12/04/2006.................2 3...................13/05/2006.................3 4...................13/06/2006.................4 5...................03/09/2006.................4 6...................04/09/2006.................4 7...................02/01/2007.................6 Exemple concret : SELECT c.id_contact, d.id_demande, d.date_demande, c.nom, c.email1FROM demande d LEFT JOIN contact c ON d.contact_id = c.id_contact id_contact....id_demande..date_demande...nom.....email1 ----------------------------------------------------------------------------------------------- 1.................1......................25/01/2006.....TOTO....toto_AT_free.fr 2.................2......................12/04/2006.....LEON....leon_AT_wanadoo.fr 3.................3......................13/05/2006.....TOTO....toto_AT_free.fr 4.................4......................13/06/2006.....PAUL1...paul_AT_neuf.fr 4.................5......................03/09/2006.....PAUL1...paul_AT_neuf.fr 4.................6.......................04/09/2006.....PAUL1...paul_AT_neuf.fr 4.................7......................02/01/2007.....PAUL2...paul_AT_neuf.fr Voila ce que je souhaiterais obtenir : id_contact..id_demande...date_demande.....nom.....email1.................nb --------------------------------------------------------------------------------- 1..................1.................25/01/2006.......TOTO.....toto_AT_free.fr..........2 2..................2.................12/04/2006.......LEON.....leon_AT_wanadoo.fr...1 3..................3.................13/05/2006.......TOTO.....toto_AT_free.fr..........2 4..................4.................13/06/2006.......PAUL1....paul_AT_neuf.fr.........4 4..................5.................03/09/2006.......PAUL1....paul_AT_neuf.fr.........4 4..................6.................04/09/2006.......PAUL1....paul_AT_neuf.fr.........4 4..................7.................02/01/2007.......PAUL2....paul_AT_neuf.fr.........4 Code pour créer les 2 tables avec les datas -- -- Structure de la table `contact`-- CREATE TABLE `contact` ( `id_contact` int(11) NOT NULL AUTO_INCREMENT, `nom` varchar(100) collate latin1_general_ci NOT NULL DEFAULT '', `email1` varchar(250) collate latin1_general_ci NOT NULL DEFAULT '', PRIMARY KEY (`id_contact`), KEY `email1` (`email1`)) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci AUTO_INCREMENT=27376;-- -- Contenu de la table `contact`-- INSERT INTO `contact` (`id_contact`, `nom`, `email1`) VALUES(1, 'TOTO', 'toto_AT_free.fr'),(2, 'LEON', 'leon_AT_wanadoo.fr'),(3, 'TOTO', 'toto_AT_free.fr'),(4, 'PAUL1', 'paul_AT_neuf.fr'),(5, 'NOEMIE', 'nono_AT_club.fr'),(6, 'PAUL2', 'paul_AT_neuf.fr');-- ---------------------------------------------------------- -- Structure de la table `demande`-- CREATE TABLE `demande` ( `id_demande` int(11) NOT NULL AUTO_INCREMENT, `date_demande` date NOT NULL DEFAULT '0000-00-00', `contact_id` int(11) NOT NULL DEFAULT '0', PRIMARY KEY (`id_demande`)) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci PACK_KEYS=0 AUTO_INCREMENT=23411;-- -- Contenu de la table `demande`-- INSERT INTO `demande` (`id_demande`, `date_demande`, `contact_id`) VALUES(1, '2006-01-25', 1),(2, '2006-04-12', 2),(3, '2006-05-13', 3),(4, '2006-06-13', 4),(5, '2006-09-03', 4),(6, '2006-09-04', 4),(7, '2007-01-02', 6); Espérant avoir exposé ma problématique le plus clairement possible, je vous remercie par avance des conseils que vous pourrez mapporter.
hcplayer Posté 27 Janvier 2007 Posté 27 Janvier 2007 Hello, ceci te conviendra peut être à vue de nez (j'ai pas testé) : SELECT id_demande,date_demande,contact_id,id_contact,nom,email1,COUNT(contact_id) AS nb FROM demande LEFT JOIN contact ON (demande.contact_id=contact.id_contact) GROUP BY contact_id;
Vincent Posté 27 Janvier 2007 Posté 27 Janvier 2007 Pour ma part, je pense qu'il y a un petit probleme de structure dans ta table : tu as des membres qui sont en doubles et tu veux décompter le nombre de fois que la même email apparait dans la table demande. Or comme tu fait la relation avec l'id, c'est chaud pour l'efficacité ! voilà une requete qui fonctionne : SELECT c.id_contact, d.id_demande, d.date_demande, c.nom, c.email1,(select count(c2.email1) from contact c2, demande d2 where c2.email1=c.email1 and c2.id_contact=d2.contact_id) as nb FROM demande d LEFT JOIN contact c ON d.contact_id = c.id_contact
Tavarlindar Posté 27 Janvier 2007 Auteur Posté 27 Janvier 2007 Bravo Vincent, ta requête fonctionne est donne le résultat escompté, mais comme tu le supputais, en terme defficacité ce nest pas cela du tout. Sur ma base de production ça plante .... Aujourdhui pour afficher avec php le résultat souhaité je suis contraint de faire ceci : < ? $requete = SELECT demande.id_demande, demande.date_demande, contact.nom, contact.email1 FROM demande LEFT JOIN contact ON demande.contact_id = contact.id_contact; $resultat = ExecRequete ($requete, $connexion); // avec ExecRequete une fonction qui utilise mysql_query() et les paramètres de connexion à la base Mysql qui vont bien. while($demandeC = mysql_fetch_object($resultat)){ $date_demande_fr = date("d-M-y", strtotime($demandeC->date_demande)); $existance = ExecRequete('SELECT count(contact.email1 ) AS nb FROM contact JOIN demande ON demande.contact_id = contact.id_contact WHERE contact.email1 = \''.$demandeC->email1.'\'', $connexion); $nb_email = mysql_result($existance, 0); //$nb_email = mysql_fetch_object ($existance); if ($nb_email > 1 ){ //$email = <font size=+2 color=red>$nb_email->nb $Nb = '('.$nb_email.')';} else { $Nb ='';}echo '<TR><TD>',$date_demande_fr, '<TD>',$demandeC->nom , '<TD>',$demandeC->email1,' ',$Nb,'</TD></TR>'; $i++; } ?> Souhaitant optimiser les temps de réponse, je me suis dit quen améliorant ma requête sql je pourrais peut-être éviter de faire une requête pour calculer le nombre de demandes au sein même dune boucle. En effet, Mysql doit ici parcourir toute la table demande et dans le même temps pour chaque enregistrement trouvé indiquer combien de demandes ont été effectué par un même contact. Malheureusement, je ne sais pas quoi faire. La présence de doublon dans ma table contact est une contrainte opérationnelle. L'un ou l'une d'entre vous a t-il (t-elle) une idée ?
Vincent Posté 27 Janvier 2007 Posté 27 Janvier 2007 Souhaitant optimiser les temps de réponse, je me suis dit quen améliorant ma requête sql je pourrais peut-être éviter de faire une requête pour calculer le nombre de demandes au sein même dune boucle.En effet, Mysql doit ici parcourir toute la table demande et dans le même temps pour chaque enregistrement trouvé indiquer combien de demandes ont été effectué par un même contact. Malheureusement, je ne sais pas quoi faire. La présence de doublon dans ma table contact est une contrainte opérationnelle. L'un ou l'une d'entre vous a t-il (t-elle) une idée ? L'idée serait alors de répeter l'info email de la table contact et de la mettre dans la table demande. C'est pas propre fonctionnellement mais opérationnellement, cela aura le mérite de supprimer 1 appel avec jointure pour faire le décompte
Tavarlindar Posté 27 Janvier 2007 Auteur Posté 27 Janvier 2007 certes c'est une idée, mais justement, je viens de pondre un module de dédoublonnage visant à ne plus avoir de doublon dans cette table contact (enfin réduire le nombre de doublon). Dupliquer l'email dans la table demande n'est pas jouable. pour info autre code qui fonctionne bien sur quelques enregistrements mais plante aussi sur une base de production : SELECT c.id_contact, d.id_demande, d.date_demande, c.nom, c.email1, COUNT(*) AS nbFROM contact c INNER JOIN demande d ON d.contact_id = c.id_contact INNER JOIN contact c2 ON c.email1 = c2.email1 INNER JOIN demande d2 ON d2.contact_id = c2.id_contactGROUP BY c.email1, d.id_demandeORDER BY d.date_demande affaire à suivre ... merci pour ton aide
Sujets conseillés
Veuillez vous connecter pour commenter
Vous pourrez laisser un commentaire après vous êtes connecté.
Connectez-vous maintenant