IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Requêtes PostgreSQL Discussion :

Calculer une moyenne sur plusieurs colonnes


Sujet :

Requêtes PostgreSQL

  1. #1
    Membre à l'essai
    Inscrit en
    Mai 2005
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 29
    Points : 14
    Points
    14
    Par défaut Calculer une moyenne sur plusieurs colonnes
    Bonjour,

    j'ai déjà cherché à gauche à droite, mais je n'ai pas trouvé de réponse à cette question apparemment assez simple...

    Mon problème est le suivant: dans une table, je stocke 4 paramètres, S1, S2, S3 et S4. Je souhaite créer une vue qui me calcule la moyenne de ces 4 paramètres pour donner un indice ind_s.

    Pour l'instant, je calcule de façon naïve:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT (s1 + s2 + s3 + s4) / 4 AS ind_s 
    FROM my_table
    Le souci est que certains paramètres peuvent parfois être NULL.

    Si mes valeurs sont: 10, 20, 30, 40, la moyenne calculée est 25
    Si mes valeurs sont: 10, 20, NULL, 40, la moyenne calculée est 17.5. Je souhaiterais qu'elle soit 23.3 ((10+20+40)/3)

    Quelqu'un a-t-il une idée?

    La requête

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT avg(s1, s2, s3, s4) AS ind_s 
    FROM my_table
    Ne fonctionne évidemment pas mais c'est le comportement que je souhaite imiter.

    Merci d'avance et meilleures salutations,

    Stéphane

  2. #2
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 782
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 782
    Points : 52 783
    Points
    52 783
    Billets dans le blog
    5
    Par défaut
    Votre table est à l’évidence mal modélisée et tout ce qui est mal modélisé conduit immanquablement à des requêtes complexes peu performantes et non évolutives, donc entrainant de la maintenance !

    Voic l'épouvantable requête qu'il faut faire suite à l’horreur que constitue votre table :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT COALESCE(s1, 0) + COALESCE(s2, 0) + COALESCE(s3, 0) + COALESCE(s4))
           / ( CASE WHEN s1 IS NULL THEN 0 ELSE 1 END 
             + CASE WHEN s2 IS NULL THEN 0 ELSE 1 END 
             + CASE WHEN s3 IS NULL THEN 0 ELSE 1 END 
             + CASE WHEN s4 IS NULL THEN 0 ELSE 1 END)   
    FROM  my_table
    Si vous aviez "sortit" ces paramètres dans une table fille, voici la requête à faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT AVG(S)
    FROM   MaTableFille
    GROUP  BY CLEF_TABLE_MERE
    Et si vous ajoutez un nouveau paramètre S5, la première requête est à refaire, la seconde non !

    Cela, s’appelle le respect des formes normales.

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  3. #3
    Membre à l'essai
    Inscrit en
    Mai 2005
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 29
    Points : 14
    Points
    14
    Par défaut
    Merci beaucoup, je vais donc revoir la normalisation de mes tables!

    meilleures salutations,

    Stéphane

  4. #4
    Modérateur

    Avatar de MaitrePylos
    Homme Profil pro
    DBA
    Inscrit en
    Juin 2005
    Messages
    5 496
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : Belgique

    Informations professionnelles :
    Activité : DBA
    Secteur : Service public

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 496
    Points : 12 596
    Points
    12 596
    Par défaut
    Tu auras rectifier la petite coquille de SqlPro

    par


  5. #5
    Membre à l'essai
    Inscrit en
    Mai 2005
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 29
    Points : 14
    Points
    14
    Par défaut
    Oui, j'avais rectifié... mais la piste de la re-modélisation semble tout de même plus évolutive! Je retourne donc à mes études :-)

    Au passage, je serais curieux de savoir s'il y a une raison "logique" au fait que l'on ne peut pas, en SQL, facilement calculer une moyenne entre plusieurs colonnes d'une même table, par exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT avg(col1, col2, col3) from mytable
    J'imagine bien que c'est n'est pas un "oubli" dans l'implémentation du langage, mais qu'il y a bien une raison conceptuelle derrière. Si quelqu'un a une piste de réflexion, ça m'intéresserait de comprendre!

    Encore merci à tous 2 pour vos réponses

    Stéphane

  6. #6
    Membre émérite
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Points : 2 890
    Points
    2 890
    Par défaut
    Citation Envoyé par stöckli Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT (s1 + s2 + s3 + s4) / 4 AS ind_s 
    FROM my_table
    Le souci est que certains paramètres peuvent parfois être NULL.

    Si mes valeurs sont: 10, 20, 30, 40, la moyenne calculée est 25
    Si mes valeurs sont: 10, 20, NULL, 40, la moyenne calculée est 17.5. Je souhaiterais qu'elle soit 23.3 ((10+20+40)/3)

    Quelqu'un a-t-il une idée?
    Tu peux utiliser une astuce spécifique à postgres consistant à transformer dynamiquement les colonnes en ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    select avg(x) from (select unnest(array[s1,s2,s3,s4]) x from mytable) s;
    unnest() est intégré à partir de la 8.4, pour les versions d'avant il faut définir une fonction d'aggrégat personnelle à la place.

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

Discussions similaires

  1. calcul de moyenne sur plusieurs plages dans une colonne
    Par Jean-luc79 dans le forum Excel
    Réponses: 2
    Dernier message: 19/12/2014, 11h20
  2. [phpBB][2] Faire une boucle sur plusieurs colonnes
    Par Vinuto dans le forum Bibliothèques et frameworks
    Réponses: 5
    Dernier message: 28/09/2007, 10h45
  3. [ul/li] Séparer une liste sur plusieurs colonnes
    Par Wookai dans le forum Balisage (X)HTML et validation W3C
    Réponses: 4
    Dernier message: 22/06/2007, 14h01
  4. [VBA-E] Eclater les valeurs d'une cellue sur plusieurs colonnes
    Par sosophie dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 13/03/2007, 08h41
  5. Réaliser une arborescence sur plusieurs colonnes
    Par vince16 dans le forum Langage
    Réponses: 1
    Dernier message: 11/11/2006, 12h33

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo