Précédent   Forum des professionnels en informatique > Bases de données > PostgreSQL > Requêtes
Requêtes Forum d'entraide sur les requêtes SQL spécifiques à PostgreSQL, les triggers, les vues, etc.
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 11/10/2011, 08h58   #1
Invité de passage
 
Inscription : mai 2005
Messages : 23
Détails du profil
Informations forums :
Inscription : mai 2005
Messages : 23
Points : 3
Points : 3
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 :
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 :
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
stöckli est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/10/2011, 10h23   #2
Rédacteur/Modérateur

 
Avatar de SQLpro
 
Homme Frédéric BROUARD
Expert SGBDR & SQL
Inscription : mai 2002
Messages : 10 959
Détails du profil
Informations personnelles :
Nom : Homme Frédéric BROUARD
Localisation : France

Informations professionnelles :
Activité : Expert SGBDR & SQL
Secteur : Conseil

Informations forums :
Inscription : mai 2002
Messages : 10 959
Points : 17 791
Points : 17 791
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 :
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 :
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
Site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
Blog SQL, SQL Server, modélisation données : http://blog.developpez.com/sqlpro
http://www.sqlspot.com : modélisation, conseils, audit, optimisation, formation
* * * * * Enseignant CNAM PACA - ISEN Toulon - CESI Aix en Provence * * * * *
SQLpro est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/10/2011, 13h16   #3
Invité de passage
 
Inscription : mai 2005
Messages : 23
Détails du profil
Informations forums :
Inscription : mai 2005
Messages : 23
Points : 3
Points : 3
Merci beaucoup, je vais donc revoir la normalisation de mes tables!

meilleures salutations,

Stéphane
stöckli est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/10/2011, 08h43   #4
Rédacteur/Modérateur
 
Avatar de MaitrePylos
 
Homme Gérard Ernaelsten
DBA & Dev PHP
Inscription : juin 2005
Messages : 3 177
Détails du profil
Informations personnelles :
Nom : Homme Gérard Ernaelsten
Âge : 39
Localisation : Belgique

Informations professionnelles :
Activité : DBA & Dev PHP
Secteur : Service public

Informations forums :
Inscription : juin 2005
Messages : 3 177
Points : 6 460
Points : 6 460
Tu auras rectifier la petite coquille de SqlPro

par

MaitrePylos est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/10/2011, 08h51   #5
Invité de passage
 
Inscription : mai 2005
Messages : 23
Détails du profil
Informations forums :
Inscription : mai 2005
Messages : 23
Points : 3
Points : 3
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 :
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
stöckli est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/10/2011, 14h44   #6
Modérateur
 
Inscription : octobre 2008
Messages : 1 508
Détails du profil
Informations personnelles :
Localisation : France, Paris (Île de France)

Informations forums :
Inscription : octobre 2008
Messages : 1 508
Points : 2 040
Points : 2 040
Citation:
Envoyé par stöckli Voir le message
Code :
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 :
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.
estofilo est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 02h45.


 
 
 
 
Partenaires

Hébergement Web