Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 9 sur 9
  1. #1
    Invité de passage
    Inscrit en
    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 !!

  2. #2
    Responsable Modération

    Avatar de ok.Idriss
    Homme Profil pro Idriss Neumann
    Consultant en SSII et ingénieur CNAM Paris (spécialité SI)
    Inscrit en
    février 2009
    Messages
    5 047
    Détails du profil
    Informations personnelles :
    Nom : Homme Idriss Neumann
    Âge : 24
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Consultant en SSII et ingénieur CNAM Paris (spécialité SI)
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2009
    Messages : 5 047
    Points : 17 468
    Points
    17 468

    Par défaut

    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
    mes cours sur DVP | initiation aux bases de données relationnelles | FAQ Linux | FAQ tests
    la programmation Shell | bonnes pratiques Bash | exercices shells scripts & Bash corrigés
    Merci aussi de lire les règles du club

    "Forgiveness does not change the past, but it does enlarge the future." (Paul Boese)
    Traduction approximative : le pardon ne change pas le passé mais élargit l'horizon de l'avenir.

  3. #3
    Invité de passage
    Inscrit en
    décembre 2012
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : décembre 2012
    Messages : 4
    Points : 3
    Points
    3

    Par défaut

    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.

  4. #4
    Responsable Modération

    Avatar de ok.Idriss
    Homme Profil pro Idriss Neumann
    Consultant en SSII et ingénieur CNAM Paris (spécialité SI)
    Inscrit en
    février 2009
    Messages
    5 047
    Détails du profil
    Informations personnelles :
    Nom : Homme Idriss Neumann
    Âge : 24
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Consultant en SSII et ingénieur CNAM Paris (spécialité SI)
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2009
    Messages : 5 047
    Points : 17 468
    Points
    17 468

    Par défaut

    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 .
    mes cours sur DVP | initiation aux bases de données relationnelles | FAQ Linux | FAQ tests
    la programmation Shell | bonnes pratiques Bash | exercices shells scripts & Bash corrigés
    Merci aussi de lire les règles du club

    "Forgiveness does not change the past, but it does enlarge the future." (Paul Boese)
    Traduction approximative : le pardon ne change pas le passé mais élargit l'horizon de l'avenir.

  5. #5
    Invité de passage
    Inscrit en
    décembre 2012
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : décembre 2012
    Messages : 4
    Points : 3
    Points
    3

    Par défaut

    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.

  6. #6
    Responsable Modération

    Avatar de ok.Idriss
    Homme Profil pro Idriss Neumann
    Consultant en SSII et ingénieur CNAM Paris (spécialité SI)
    Inscrit en
    février 2009
    Messages
    5 047
    Détails du profil
    Informations personnelles :
    Nom : Homme Idriss Neumann
    Âge : 24
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Consultant en SSII et ingénieur CNAM Paris (spécialité SI)
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2009
    Messages : 5 047
    Points : 17 468
    Points
    17 468

    Par défaut

    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
    mes cours sur DVP | initiation aux bases de données relationnelles | FAQ Linux | FAQ tests
    la programmation Shell | bonnes pratiques Bash | exercices shells scripts & Bash corrigés
    Merci aussi de lire les règles du club

    "Forgiveness does not change the past, but it does enlarge the future." (Paul Boese)
    Traduction approximative : le pardon ne change pas le passé mais élargit l'horizon de l'avenir.

  7. #7
    Invité de passage
    Inscrit en
    décembre 2012
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : décembre 2012
    Messages : 4
    Points : 3
    Points
    3

    Par défaut

    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

  8. #8
    Membre chevronné
    Homme Profil pro Frédéric
    Inscrit en
    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 : 612
    Points
    612

    Par défaut

    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é.

  9. #9
    Responsable Modération

    Avatar de ok.Idriss
    Homme Profil pro Idriss Neumann
    Consultant en SSII et ingénieur CNAM Paris (spécialité SI)
    Inscrit en
    février 2009
    Messages
    5 047
    Détails du profil
    Informations personnelles :
    Nom : Homme Idriss Neumann
    Âge : 24
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Consultant en SSII et ingénieur CNAM Paris (spécialité SI)
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2009
    Messages : 5 047
    Points : 17 468
    Points
    17 468

    Par défaut

    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.
    mes cours sur DVP | initiation aux bases de données relationnelles | FAQ Linux | FAQ tests
    la programmation Shell | bonnes pratiques Bash | exercices shells scripts & Bash corrigés
    Merci aussi de lire les règles du club

    "Forgiveness does not change the past, but it does enlarge the future." (Paul Boese)
    Traduction approximative : le pardon ne change pas le passé mais élargit l'horizon de l'avenir.

+ Répondre à la discussion
Cette discussion est résolue.

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •