Aller au contenu

Comment utiliser un COUNT dans une requête SQL


Sujets conseillés

Posté

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.email1
FROM 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.

Posté

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;

Posté

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

Posté

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 ?

:wacko:

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

:wacko:

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 :D

Posté

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. :nonono:

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 nb
FROM 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_contact
GROUP BY c.email1, d.id_demande
ORDER BY d.date_demande

affaire à suivre ...

merci pour ton aide

Veuillez vous connecter pour commenter

Vous pourrez laisser un commentaire après vous êtes connecté.



Connectez-vous maintenant
×
×
  • Créer...