Page 1 sur 1

à la recherche d'une requête magique...

Posté : 26 mai 2009, 11:28
par Sofa
Bonjour à tous,

Je réalise en se moment une application en php, et j'aurais besoin d'une requête pouvant m'apporter ce dont j'ai besoin.

J'ai donc une requête :

Code : Tout sélectionner

select fiche.fi_dateCreation,fiche.fi_adr_id,adresse.adr_localite from fiche,adresse where fiche.fi_adr_id = adresse.adr_id and fi_dateCreation > "2009-05-24";
Qui m'affiche :

Code : Tout sélectionner

fi_dateCreation fi_adr_id adr_localite 2009-05-25 1 PARIS 2009-05-25 2 PARIS 2009-05-25 3 BORDEAUX 2009-05-25 4 CAEN
Jusqu'ici tout est normal, je cherche cependant à partir de cette requête obtenir une table contenant les informations suivantes :

Code : Tout sélectionner

adr_localite nombreDeFois PARIS 2 BORDEAUX 1 CAEN 1
C'est à dire avoir le nombre de fois d'apparition en correspondance a l'occurence.

Je ne sait pas si ce ci est réalisable, mais je ne pense pas avoir les compétences nécessaire en la matière pour pouvoir résoudre mon problème tout seul.
Je compte sur vous pour m'éclairer si vous avez une idée.

Merci beaucoup d'avance,

Sofa

PS : N'ayant pas besoin de vous indiquer la constitution de ma table, je me permet d'écrire "CREATE TABLE" afin que le site me laisse écrire ce message. Merci de votre compréhension.

Posté : 26 mai 2009, 11:59
par sadeq
Bonjour Sofa,

Tu peux créer ta table temporaire à base d'un SELECT pour obtenir la seconde requête que tu veux sans passer par la première requête. Voici comment:

Code : Tout sélectionner

CREATE TABLE nombre_localite SELECT adresse.adr_localite, count(adresse.adr_localite) as nombreDeFois FROM fiche,adresse WHERE fiche.fi_adr_id = adresse.adr_id and fiche.fi_dateCreation > "2009-05-24" GROUP BY adresse.adr_localite;
Il faut noter que quand tu veux faire un calcul de regroupement comme le compte des adresses par localité, il faut éviter d'inclure dans le SELECT tout champ qui peut afficher le détail comme les clés primaires ou les index unique comme par exemple adr_id. Car le regroupement par GROUP BY va regrouper les même valeurs des champs qui contiennent des doublons et si SELECT ne contient que les champs du regroupement, SQL retourne une valeur distinct des occurrences regroupées.

Moralité, quand on regroupe pour faire des calculs de synthèses comme un comptage, moyenne ou somme par critère, il faut choisir des champs de regroupement qui jouent le rôle d'index avec doublons.

Posté : 26 mai 2009, 13:26
par Sofa
Bonjour sadeq,

Je viens d'essayer ta requête et tout marche à merveille, je te remercie :D.
Crée une table temporaire, est quelque chose que je n'avais pas envisagé, c'est une très bonne idée!
Je ferais attention aux ids, je ne savais pas que cela pouvait poser problème.

Merci et bonne journée :)

Sofa

Posté : 26 mai 2009, 13:44
par sadeq
Il faut noter aussi que le fait de créer des tables temporaires basées sur des requêtes n'est pas une bonne idée si ce n'est pas nécessaire, car le contenu de la table ne sera pas dynamique, c'est à dire que les nombres calculés dans ton exemple ne changeront pas au fil du temps à la réutilisation de la table. La requête est utilisée pour créer la table et ne reste pas attachée à la table.

Par contre, si tu veux créer une "table dynamique" basée sur une requête et qui change de contenu à chaque ouverture dans le temps, il faut utiliser à ce moment là : UNE VUE. Comme ça:

Code : Tout sélectionner

CREATE VIEW vue_nombre_localite AS SELECT adresse.adr_localite, count(adresse.adr_localite) as nombreDeFois FROM fiche,adresse WHERE fiche.fi_adr_id = adresse.adr_id and fiche.fi_dateCreation > "2009-05-24" GROUP BY adresse.adr_localite;
La vue est considérée par SQL comme une table sauf que le contenu d'une vue est dynamique et en lecture seule car elle est attachée toujours à une requête SELECT qui sera toujours exécutée quand la vue est ouverte.

Voici un exemple d'utilisation de la vue "vue_nombre_localite":

Code : Tout sélectionner

SELECT * FROM vue_nombre_localite;
Dans cet exemple, SQL va ouvrir la vue "vue_nombre_localite" en exécutant son code SQL qui lui est attaché à la création. C'est à dire celui_là:

Code : Tout sélectionner

SELECT adresse.adr_localite, count(adresse.adr_localite) as nombreDeFois FROM fiche,adresse WHERE fiche.fi_adr_id = adresse.adr_id and fiche.fi_dateCreation > "2009-05-24" GROUP BY adresse.adr_localite;
Et retournera toujours un résultat actualisé contrairement à la technique de création de table temporaire.

Dans ce cas, me dirais-tu, à quoi sert le CREATE TABLE basé sur SELECT? hé bien, il sert par exemple à éclater une table en plusieurs tables pour faire une répartition de données ou un archivage filtré. Comme par exemple, de créer des tables régionales pour répartir les ventes de produits par région. Cette technique est le contraire de la centralisation ou la consolidation de données.

Posté : 26 mai 2009, 15:20
par Sofa
D'accord, je vois ce que tu veux dire.
J'avais déjà entendu parlé des vues, mais je ne m'en suis jamais servi.

Grâce à ta méthode je crée la table, lit les informations, puis la DROP, saurais-tu me dire si cette méthode utilise plus de ressource, ou d'accès serveur que la méthode des vues ?
Sachant que je n'ai besoin de faire qu'une seul lecture par table crée.

Merci pour ton aide.

Sofa

Posté : 26 mai 2009, 15:36
par sadeq
Tout à fait, le fait de créer une table temporaire pour qu'en suite la supprimer et la recréer au besoin, consomme plus de ressources que le fait d'utiliser une vue. Car la vue n'exigera pas de manipulations entre le temps de sa création et les réutilisations. La vue se crée une fois et reste dynamique.

En terme de ressources, la vue est la plus légère, elle ne contient pas de données physiques comme une table et ne nécessite pas d'opération sur sa structure car une vue est une simple requête exécutable.

Dans ton cas, je te recommande la vue.

Posté : 26 mai 2009, 15:51
par Sofa
Je viens d'essayer la méthode des vues, j'ai peut etre mal recopié, mais lorsque j'éxécute le code suivant :

Code : Tout sélectionner

CREATE VIEW vue_nombre_localite AS SELECT adresse.adr_localite, count(adresse.adr_localite) as nombreDeFois FROM fiche,adresse WHERE fiche.fi_adr_id = adresse.adr_id and fi_dateCreation >='2009-05-25' and fi_dateCreation <'2009-06-01' GROUP BY adresse.adr_localite;
il m'affiche l'erreur suivante :

Code : Tout sélectionner

Error Code : 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VIEW vue_nombre_localite AS SELECT adresse.adr_localite, count(adresse.adr_l' at line 1 (0 ms taken)
Je ne suis pas sur de comprendre quel est le problème...

Posté : 26 mai 2009, 16:19
par sadeq
Quelle est la version de ton MYSQL? Car cette commande a été ajoutée en MySQL 5.0

Posté : 26 mai 2009, 16:22
par Sofa
Lorsque je vais sur php my admin, il m'indique que la version est :
MySQL 4.1.21-standard

Posté : 26 mai 2009, 16:24
par Sofa
Oups, je n'avais pas vu la fin de ta réponse, ce n'est donc pas possible de faire des vues :(
Je vais donc refaire avec des tables tanpis.
Merci encore pour ton aide.

Sofa

Posté : 26 mai 2009, 16:30
par sadeq
Mais non, il faut mettre à jour ton MySQL à la dernière version. On n'avance pas en reculant.
Les vues ne sont pas une innovation de la version 5, c'est un standard SQL. Mais MySQL essaye simplement de rattraper son retard en mettant à jour continuellement son support SQL pour s'aligner avec les standards SQL.

Posté : 26 mai 2009, 16:41
par Sofa
Je n'ai malheuresement pas les droits pour le faire :( .
Ce n'est pas mon serveur, et je ne peut pas espérer une mise à jour...
En tout cas, merci beaucoup pour tout, tu m'as bien débloqué!
A une prochaine :wink:.

Sofa