compter su 2 tableaux

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : compter su 2 tableaux

par Hubert Roksor » 16 oct. 2007, 15:02

@debe: ce qu'il faut retenir, c'est que si ce message apparaît systématiquement à chaque nouveau sujet, ce n'est pas juste parce qu'on aime bien embêter les gens, c'est parce que sans ces informations il est très difficile (et prend plus de temps) de correctement répondre à tes questions.

Pour référence :
Rappel pratique - n'oubliez pas de :
  • suivre ces quelques conseils de débogage
  • préciser quel SGBD vous utilisez ainsi que sa version
  • utiliser les balises

    Code : Tout sélectionner

    [/b] et [b]
    [/b] pour afficher vos requêtes SQL[/color]
  • poster le schéma des tables pertinentes à votre requête sous la forme d'une instruction "CREATE TABLE" (vous pouvez retirer les colonnes qui ne sont pas utilisées dans les requêtes problématiques)
  • si nécessaire, poster un échantillon des données
Si on demande de poster le schéma de la table, c'est pour facilement la recréer en local (un copier/coller prend 5s) pour vérifier que la solution qu'on propose est pertinente. Pareil pour l'échantillon de données.

Concernant "ça marche pas", le problème c'est qu'il y a une infinité de raisons pour lesquelles une chose peut ne pas se dérouler comme prévu. Est-ce qu'il y a un message d'erreur, et si oui lequel ? (voir les conseils de débogages) Si ce n'est pas un message d'erreur, c'est que le résultat obtenu diffère du résultat escompté et dans ce cas, quel est le résultat obtenu ? quel est le résultat escompté ? En quoi diffèrent-ils l'un de l'autre ?

Si on demande la version du SGBD c'est pour éviter de passer du temps à répondre à partir de fonctions (sous-requêtes, vues, procédures, etc...) qui n'existeraient pas dans toutes les versions de la base de données que tu utilises. Là encore ce serait dommage de passer du temps pour rien.


Pour en revenir au sujet, je ne suis pas fan des sous-requêtes dans la clause SELECT parce qu'elles ne sont pas optimisées par MySQL, et je pense que les performances vont se dégrader de façon significative au fur et à mesure que la table grossit. En fait, j'aurais pû vérifier cette théorie par moi-même si le schéma des tables était disponible, ainsi qu'un échantillon des données. J'aurais même réfléchit à une alternative si je n'avais pas passé le temps qui m'était imparti à expliquer pourquoi certains messages s'affichent en rouge...

par sadeq » 15 oct. 2007, 22:06

OK, en fait j'ai oublié de mettre la relation entre la requête principale et les sous-requêtes pour qu'elles puissent compter à chaque fois pour le même titre traité par la requête principale.

Sachant que les sous-requêtes peuvent voir les champs de leur mère la requête principale exactement comme des variables globales, on va utiliser id_inscrip comme paramètre de jointure:

Code : Tout sélectionner

SELECT titre, (SELECT COUNT(I.id_inscrip) FROM inscrip_proxi I WHERE etat = 'inscrit' And I.id_inscrip= P.id_inscrip) As inscrits, (SELECT COUNT(I.id_inscrip) FROM inscrip_proxi I WHERE etat = 'attente' And I.id_inscrip= P.id_inscrip) As attentes FROM acti_proxi P ORDER BY titre
P : surnom ou alias de la table acti_proxi
I : surnom ou alias de la table inscrip_proxi
La relation entre les sous-requêtes et la requête principale est : P.id_inscrip= I.id_inscrip (clé primaire = clé étrangère)

NB. sans cette relation les sous-requêtes retournent toujours le compte total tout titre confondu. Ce qui est effectivement incorrect.
Il faut savoir aussi que les sous-requêtes sont supportées à partir de Mysql 4.1 je pense.

par debe » 15 oct. 2007, 20:36

cela serait sans doute plus clair avec le code

Code : Tout sélectionner

SELECT titre, (SELECT COUNT(id_inscrip) FROM inscrip_proxi WHERE etat = 'inscrit') As inscrits, (SELECT COUNT(id_inscrip) FROM inscrip_proxi WHERE etat = 'attente') As attentes FROM acti_proxi ORDER BY titre
[/code]

toujours pb dans la requete 2 tables

par debe » 15 oct. 2007, 20:31

bonsoir,
1) tout d'abord, toutes mes excuses à l'administrateur. j'avais vu en effet qu'il ne fallait pas dire "cela ne marche pas", mais j'avais compris que c'était dans le titre car trop flou.
bon, les deux bonjour, c'est cafouillage ... mais il faut mieux cela que les impolitesses souvent rencontrées :wink:

2) un grand merci pour la réponse qui, en même temps, m'explique très bien le processus. seulement, les résultats qui sont retournés ne sont pas exacts
bla bla bla karting ados
inscrits 3
attentes 1

**********
une activité test
inscrits 3
attentes 1

alors que j'ai :
une activité test => 2 inscrits | 1 attente
bla bla bla karting ados => 1 inscrits | 0 attente

par Tracker » 15 oct. 2007, 14:04

Il me semble que COUNT(etat = 'inscrit') ou COUNT(etat = 'attente') fonctionnent
Err, non.

Au mieux tu peux avoir un SUM(IF(etat='inscrit', 1, 0)), qui oblitère toute chance d'utiliser un index.
Promis la prochaine fois je teste :wink:
Ca m'apprendra à lire de docs sur de site à la c..

Re: compter su 2 tableaux

par Hubert Roksor » 15 oct. 2007, 13:41

bonjour,
bonjour et merci

[...]

cela ne marche pas
Cher(e) debe,

Je constate que tu as bien saisi le concept de dire "bonjour" et "merci" (un de chaque suffit en général), néanmoins ce serait bien d'aller un petit peu plus loin et suivre les consignes affichées en rouge sur ton écran, comme par exemple poster le schéma de ta table ou le message d'erreur reçu. De plus je constate avec regret que tu n'as pas lu les règlements généraux, puisque ceux-ci spécifient que la phrase "ça ne marche pas" peut valoir un bannissement d'une durée illimitée :(

par Hubert Roksor » 15 oct. 2007, 13:37

Il me semble que COUNT(etat = 'inscrit') ou COUNT(etat = 'attente') fonctionnent
Err, non.

Au mieux tu peux avoir un SUM(IF(etat='inscrit', 1, 0)), qui oblitère toute chance d'utiliser un index.

par Tracker » 15 oct. 2007, 11:34

Requête générale

Code : Tout sélectionner

SELECT titre, (SELECT COUNT(id_insc) FROM inscrip_proxi WHERE etat = 'inscrit') As inscrits, (SELECT COUNT(id_insc) FROM inscrip_proxi WHERE etat = 'attente') As attentes, FROM acti_proxi ORDER BY titre
Il me semble que COUNT(etat = 'inscrit') ou COUNT(etat = 'attente') fonctionnent, donc y'a possibilité de raccourcir l'écriture.

Tracker.

par sadeq » 15 oct. 2007, 11:31

En temps normal, t'as deux requêtes de calcul différentes car deux calculs différents.
Mais l'on peut regrouper les deux calculs dans une seule requête en utilisant ce que l'on appelle une sous-requête.

Découpant d'abord le problème en deux parties pour mieux comprendre:
1. Calcul du nombre des inscrits.
2. Calcul du nombre des attentes.

1. Calcul du nombre des inscrits:

Code : Tout sélectionner

SELECT titre, COUNT(id_insc) As inscrits FROM inscrip_proxi JOIN acti_proxi ON inscrip_proxi.id_acti=acti_proxi.id_acti WHERE etat = 'inscrit' ORDER BY titre
On compte ici les id_inscrit dont l'etat='inscrit' pour éliminer ceux en attente. La table où le comptage doit se faire est "inscrip_proxi". La jointure avec la table "acti_proxi" sert simplement pour avoir le "titre" et ORDER BY pour classer le résultat par titre.

2. Calcul du nombre des attentes:

Code : Tout sélectionner

SELECT titre, COUNT(id_insc) As attentes FROM inscrip_proxi JOIN acti_proxi ON inscrip_proxi.id_acti=acti_proxi.id_acti WHERE etat = 'attente' ORDER BY titre
On compte ici les id_inscrit dont l'etat='attente' pour éliminer ceux inscrits. La table où le comptage doit se faire est "inscrip_proxi". La jointure avec la table "acti_proxi" sert simplement pour avoir le "titre" et ORDER BY pour classer le résultat par titre.

Généralisation:
Pour inclure les deux requêtes 1 et 2 dans une seule. Il faut écrire une structure de sous-requêtes dans le cadre d'une requête principale qui elle doit fournire les données communes entre les requêtes 1 et 2.

En effet, on remarque que 1 et 2 sélectionnent toutes les deux le titre à partir de la table "acti_proxi"
La requête principale doit alors effectuer cette tâche une fois alors que les deux sous-requêtes doivent se spécialiser dans le comptage.
Requête principale

Code : Tout sélectionner

SELECT titre, FROM acti_proxi ORDER BY titre
Requêtes spécialisées: (Changement = ne sélectionnent plus le titre)
Requête 1:

Code : Tout sélectionner

SELECT COUNT(id_insc) As inscrits FROM inscrip_proxi WHERE etat = 'inscrit'
Requête 2:

Code : Tout sélectionner

SELECT COUNT(id_insc) As attentes FROM inscrip_proxi WHERE etat = 'attente'
Maintenant, il faut faire la liaison entre la requête principale et les requêtes spécialisées de sorte que ces dernières soient utilisées par la requête principale comme des champs calculés.
Ce qui donne l'architecture de générallisation suivante:
Requête générale

Code : Tout sélectionner

SELECT titre, (SELECT COUNT(id_insc) FROM inscrip_proxi WHERE etat = 'inscrit') As inscrits, (SELECT COUNT(id_insc) FROM inscrip_proxi WHERE etat = 'attente') As attentes, FROM acti_proxi ORDER BY titre

compter su 2 tableaux

par debe » 12 oct. 2007, 13:30

bonjour,
bonjour et merci

j'ai une table acti_proxi avec champ id_acti, titre
et une table inscrip_proxi avec champ id_insc,id_acti,etat

le champ 'etat' et peut avoir la valeur 'inscrit' ou 'attente'
je voudrais compter combien il y a d'inscrit, et combien sont en attente

et l'afficher dans un truc du style :
activité escalade : il y a 3 inscrits et 3 sur liste d'attente

lorsque je fais

Code : Tout sélectionner

$sql="SELECT titre, COUNT(inscrit WHERE etat LIKE inscrit) as combien COUNT(inscrit WHERE etat LIKE attente) as combien2 FROM inscrip_proxi LEFT JOIN acti_proxi ON inscrip_proxi.id_acti=acti_proxi.id_acti GROUP BY titre ORDER BY titre";
cela ne marche pas