Précédent   Forum du club des développeurs et IT Pro > Bases de données > MySQL > Requêtes
Requêtes Forum d'entraide sur les requêtes MySQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 26/12/2012, 10h43   #1
kiriaphil
Invité de passage
 
Inscription : décembre 2012
Messages : 4
Détails du profil
Informations forums :
Inscription : décembre 2012
Messages : 4
Points : 3
Points : 3
Par défaut Sélection avec SUM ou COUNT ou pas possible ?

Bonjour,

Ma table Hotel se décrit par Num_Chambre, Carac1, Carac2, Carac3, Carac4, Carac5

J'aimerais pouvoir mettre une note à chaque chambre. Pour se faire je dois compter le nombre de caractéristique qu'à la chambre en question.
Pour chaque caractéristique je peux avoir les valeurs X, 1, 2.
Si la chambre a les caractéristiques :
  • 1 = 1,
  • 2 = X,
  • 3 = 2,
  • 4 = 1,
  • 5 = 1
j'aimerais comptabiliser les caractéristiques = 1 puis = 2.
Résultat
  • 3 caractéristiques à 1 et,
  • 1 caractéristique à 2.

Ainsi je pourrais lui mettre une note, qui sera différente d'une autre chambre ayant toutes les caractéristiques avec une note à 1.

C'est pourquoi je ne peux pas faire une simple somme des notes de chaque caractéristique parce que je ne pourrais pas différencier la chambre de l'exemple (où la somme aurait fait 5) de la chambre dont toutes les caractéristiques serait à 1 (ce qui fait également 5).

Auriez vous une idée de comment faire?
Est-ce possible avec une requête SQL?

Merci par avance pour votre aide !!
kiriaphil est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/12/2012, 12h08   #2
ok.Idriss
Responsable Modération

 
Avatar de ok.Idriss
 
Homme Idriss Neumann
Consultant en SSII et auditeur au CNAM Paris (ingénieur SI)
Inscription : février 2009
Messages : 3 775
Détails du profil
Informations personnelles :
Nom : Homme Idriss Neumann
Âge : 22
Localisation : France, Essonne (Île de France)

Informations professionnelles :
Activité : Consultant en SSII et auditeur au CNAM Paris (ingénieur SI)

Informations forums :
Inscription : février 2009
Messages : 3 775
Points : 12 118
Points : 12 118
Bonjour.

Comme il s'agit de colonnes différentes, un COUNT ne fonctionnera pas, il fonctionnerait s'il s'agissait d'une même colonne pour des tuples différents.

En SQL standard je ne vois pas trop de solution par contre c'est faisable assez facilement avec de nombreux langages. Tu pourrais même faire une procédure stockée pour ça à la limite si la syntaxe MySQL te le permet.

Voici un exemple d'algorithme :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
ajout_array(array_hash, valeur){
    SI valeur est une clef de array_hash ET valeur != 'X' ALORS
        array_hash[valeur]=array_hash[valeur]+1;
    SINON SI valeur != 'X' ALORS
        array_hash[valeur]=1;
    FIN SI
}
 
sql="SELECT Num_Chambre, Carac1, Carac2, Carac3, Carac4, Carac5 FROM TABLE";
 
resultat=execution(sql);
 
POUR CHAQUE tuple de resultat FAIRE
    array_hash = new array();
    ajout_array(array_hash, tuple.Carac1);
    ajout_array(array_hash, tuple.Carac2);
    ajout_array(array_hash, tuple.Carac3);
    ajout_array(array_hash, tuple.Carac4);
    ajout_array(array_hash, tuple.Carac5);
 
    Afficher "Voici le détail des carractéristiques pour " + tuple.NumChambre + " : ";
    POUR CHAQUE clef de array_hash FAIRE
        Afficher "Pour la valeur " + clef + " : " + array_hash[clef] + " occurrences";
    FIN POUR
FIN POUR
Algo à adapter en fonction du besoin. Par exemple tu peux rajouter un paramètre NumChambre en entrée. Tu peux retourner le tableau au lieu de l'afficher (dans ce cas faudra faire un tableau 2D)...

Toutefois, il aurait été plus intelligent d'avoir un schéma des tables plus relationnel comme ceci :

Code :
Chambre(NumChambre, ...) -0,5-(posséder(note))-0,n-Carractéristiques(NumCarractéristique, ...)
Et ainsi d'avoir les tables suivantes :

Code :
1
2
3
Chambre(NumChambre, ...)
Carractéristiques(NumCarractéristique, ...)
Posseder(NumChambre#, NumCarractéristique#, note)
Tu pourrais même le simplifier à :

Code :
1
2
Chambre(NumChambre, ...)
Posseder(NumChambre#, NumCarractéristique, note)
Si l'entité "Carractéristique" ne contient rien d'autre qu'un id.

En toute rigueur ça impliquerait d'avoir un traitement qui vérifie que la relation "Posseder" ne contient pas plus de 5 tuples pour un même NumChambre (ce qui n'est pas sorcier) mais tu tirerait les deux gros avantages suivants :
- Avec une simple requête d'agrégat, là tu pourrait satisfaire ton besoin :

Code :
1
2
3
4
SELECT Note, COUNT(NumCarractéristique)
FROM Posseder
WHERE NumChambre = XXX
GROUP BY Note;
- Ça t'évites en plus l'horrible bidouille de la valeur "X" que tu utilise actuellement (par exemple si pas de note pour Carac 3 pour la chambre 1, pas d'entrées dans "Posséder" pour NumCarractéristique = 3 et NumChambre = 1).

Dès lors que tu as des colonnes aux significations identiques, c'est de la redondance et, sauf si une contrainte de perf t'en empêche (parce que tu veux éviter les grosses jointures...), il faut créer une table associative comme dans l'exemple précédant.

Cordialement,
Idriss
ok.Idriss est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/12/2012, 12h50   #3
kiriaphil
Invité de passage
 
Inscription : décembre 2012
Messages : 4
Détails du profil
Informations forums :
Inscription : décembre 2012
Messages : 4
Points : 3
Points : 3
Merci, c'est bien ce qu'il me semblait, une requête ne suffit pas.
La solution de plusieurs tables est surement le plus propre et le plus maintenable par la suite.

Ma table étant déjà rempli je ne peux plus me permettre de revoir la conception. Je vais partir sur la solution de sauvegarde des tuples.

Merci pour ta réponse. Je laisse ouvert la porte quelques jours pour savoir si d'autres aurait une solution.
kiriaphil est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/12/2012, 13h04   #4
ok.Idriss
Responsable Modération

 
Avatar de ok.Idriss
 
Homme Idriss Neumann
Consultant en SSII et auditeur au CNAM Paris (ingénieur SI)
Inscription : février 2009
Messages : 3 775
Détails du profil
Informations personnelles :
Nom : Homme Idriss Neumann
Âge : 22
Localisation : France, Essonne (Île de France)

Informations professionnelles :
Activité : Consultant en SSII et auditeur au CNAM Paris (ingénieur SI)

Informations forums :
Inscription : février 2009
Messages : 3 775
Points : 12 118
Points : 12 118
Citation:
Ma table étant déjà rempli je ne peux plus me permettre de revoir la conception. Je vais partir sur la solution de sauvegarde des tuples.
Sauvegarder les tuples dans quel sens ?

Sinon, si ta volumétrie n'est pas trop importante, tu peux faire une moulinette qui remplie tes nouvelles tables à partir des anciennes. Puis supprimer les anciennes et renommer les nouvelles si l'insertion s'est bien passée .
ok.Idriss est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/12/2012, 13h16   #5
kiriaphil
Invité de passage
 
Inscription : décembre 2012
Messages : 4
Détails du profil
Informations forums :
Inscription : décembre 2012
Messages : 4
Points : 3
Points : 3
Par sauvegarder des tuples je veux dire : je parcours ma table occurrence par occurrence et pour chaque occurrence je calcul la note. C'est ta première solution.
kiriaphil est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/12/2012, 13h46   #6
ok.Idriss
Responsable Modération

 
Avatar de ok.Idriss
 
Homme Idriss Neumann
Consultant en SSII et auditeur au CNAM Paris (ingénieur SI)
Inscription : février 2009
Messages : 3 775
Détails du profil
Informations personnelles :
Nom : Homme Idriss Neumann
Âge : 22
Localisation : France, Essonne (Île de France)

Informations professionnelles :
Activité : Consultant en SSII et auditeur au CNAM Paris (ingénieur SI)

Informations forums :
Inscription : février 2009
Messages : 3 775
Points : 12 118
Points : 12 118
Et sinon quelle est la volumétrie actuelle de ta bdd ? (Combien de tuples, quelle taille, etc).

Si j'ai bien compris, il s'agit des chambres d'un hôtel, donc ça ne devrait pas dépasser le millier de tuples. Vu la taille des colonnes de ton schéma, ça reste une petite volumétrie et ça vaut surement le coup de faire une moulinette afin de remettre tout bien d'équerre

Faudra le faire en plusieurs étapes :

1 - Tu créer les nouvelles table avec un suffixe "tmp" (par exemple) pour celle dont le nom est déjà occupé.
2 - Tu applique ta moulinette afin de les remplir à partir de l'ancienne table.
3 - Tu vérifie que tout est bien inséré et cohérent (tu peux t'aider d'un script pour ça qui fait une sorte de diff entre ton ancienne table et les nouvelles => pour chaque chambre, ais-je bien les même notes sur l'ancienne table et les nouvelles ?).
4 - Si tout est OK, tu supprime ton ancienne table et tu renomme la nouvelle table portant le flag "TMP". Si c'est pas OK, l'ancienne table n'aura pas été impactée, et tu ne fera pas de régression ainsi. Si le taux d'erreur est faible, tu pourra aussi le corriger à la main en te calquant sur les valeurs de l'ancienne table mais tu ne devrait pas avoir à en venir là.

En plus, tu devrait faire un dump juste avant cette manip donc au pire des cas, rebasculer sur ce dump.

Cordialement,
Idriss
ok.Idriss est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/12/2012, 14h08   #7
kiriaphil
Invité de passage
 
Inscription : décembre 2012
Messages : 4
Détails du profil
Informations forums :
Inscription : décembre 2012
Messages : 4
Points : 3
Points : 3
Non non tu as raison vaut mieux que je fasse ce que tu dis. J'ai une centaine de tuple, même à la main c'est faisable.

Merci encore pour ton aide.

A bienôt
kiriaphil est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 27/12/2012, 11h35   #8
Fred_34
Membre expérimenté
 
Homme Frédéric
Inscription : juin 2011
Messages : 442
Détails du profil
Informations personnelles :
Nom : Homme Frédéric
Localisation : France

Informations forums :
Inscription : juin 2011
Messages : 442
Points : 576
Points : 576
C'est surement faisable avec une seule requête :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
SELECT num_chambre, nbCar1, nbCar2
FROM
(
	SELECT num_chambre, @nbCar1:=0, @nbCar2:=0,
		IF(carac1=1,@nbCar1:=@nbCar1+1,IF(carac1=2,@nbCar2:=@nbCar2+1,0)),
		IF(carac2=1,@nbCar1:=@nbCar1+1,IF(carac2=2,@nbCar2:=@nbCar2+1,0)),
		IF(carac3=1,@nbCar1:=@nbCar1+1,IF(carac3=2,@nbCar2:=@nbCar2+1,0)),
		IF(carac4=1,@nbCar1:=@nbCar1+1,IF(carac4=2,@nbCar2:=@nbCar2+1,0)),
		IF(carac5=1,@nbCar1:=@nbCar1+1,IF(carac5=2,@nbCar2:=@nbCar2+1,0)),
		@nbCar1 AS nbCar1, @nbCar2 AS nbCar2
 FROM hotel
) tmp
Mais il est vraiment préférable de faire ce qu'Idriss t'a conseillé.
Fred_34 est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 27/12/2012, 11h40   #9
ok.Idriss
Responsable Modération

 
Avatar de ok.Idriss
 
Homme Idriss Neumann
Consultant en SSII et auditeur au CNAM Paris (ingénieur SI)
Inscription : février 2009
Messages : 3 775
Détails du profil
Informations personnelles :
Nom : Homme Idriss Neumann
Âge : 22
Localisation : France, Essonne (Île de France)

Informations professionnelles :
Activité : Consultant en SSII et auditeur au CNAM Paris (ingénieur SI)

Informations forums :
Inscription : février 2009
Messages : 3 775
Points : 12 118
Points : 12 118
Ah la syntaxe MySQL le permet , merci pour cette information

Bon sinon quand je disait "pas faisable en une requête" je parlais d'une requête en SQL standard. Après de toute façon, il est préférable de partir sur une conception propre ce qui simplifiera la requête.
ok.Idriss est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 09h22.


 
 
 
 
Partenaires

Hébergement Web