Précédent   Forum des professionnels en informatique > Bases de données > MySQL > SQL Procédural
SQL Procédural Forum d'entraide sur les triggers, les procédures stockées et les fonctions en MySQL
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 22/08/2006, 14h49   #1
Candidat au titre de Membre du Club
 
Inscription : mai 2005
Messages : 30
Détails du profil
Informations forums :
Inscription : mai 2005
Messages : 30
Points : 12
Points : 12
Par défaut opération sur des champs déjà manipulés

bonjour,
je voulais simplement savoir pourquoi il n'est pas possible d'effectuer, dans une requète SELECT, une opération sur des champs qui sont déjà le résultat d'autres opérations:

petit exemple très simple pour illustrer:
Code :
1
2
3
4
5
6
 
SELECT
     MAX(nb) AS nb_max,
     MIN(nb) AS nb_min,
     ( nb_max - nb_min ) AS ecart
FROM tbl_nombres
cette requète renvoie l'erreur
Code :
Unknown COLUMN 'nb_max' IN 'field list'
j'ai seulement MySql 4; faut-il obligatoirement utiliser les fonctions ou procédures ou vues de MySql 5 pour cela?
fred23195 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/08/2006, 15h02   #2
Modérateur
 
Avatar de Cybher
 
Homme Michel
Consultant informatique
Inscription : mai 2005
Messages : 3 006
Détails du profil
Informations personnelles :
Nom : Homme Michel
Âge : 29
Localisation : France

Informations professionnelles :
Activité : Consultant informatique
Secteur : Conseil

Informations forums :
Inscription : mai 2005
Messages : 3 006
Points : 4 039
Points : 4 039
salut,

tu ne peux pas,sauf erreur de ma part mettre des alias directement apres le select

je ferais plus ceci :
Code :
1
2
3
4
5
SELECT
     MAX(nb) AS nb_max,
     MIN(nb) AS nb_min,
     ( MAX(nb) - MIN(nb) ) AS ecart
FROM tbl_nombres
Cybher est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/08/2006, 15h14   #3
Candidat au titre de Membre du Club
 
Inscription : mai 2005
Messages : 30
Détails du profil
Informations forums :
Inscription : mai 2005
Messages : 30
Points : 12
Points : 12
effectivement, on ne peut pas et c'est justement mon grand désarroi:

parceque là, j'ai fait un exemple simplissime avec juste MAX et MIN;

mais dans mon utilisation, les champs nb_max et nb_min sont des résultats de sous-requètes complexes avec des clauses WHERE et tout et tout, donc je ne peux absolument pas répéter les champs complets pour le calcul du champ ecart !

je dois donc migrer sous MySql 5 et utiliser des VIEW ou PROCEDURE ou FUNCTION ?
fred23195 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/08/2006, 15h20   #4
Modérateur
 
Avatar de Cybher
 
Homme Michel
Consultant informatique
Inscription : mai 2005
Messages : 3 006
Détails du profil
Informations personnelles :
Nom : Homme Michel
Âge : 29
Localisation : France

Informations professionnelles :
Activité : Consultant informatique
Secteur : Conseil

Informations forums :
Inscription : mai 2005
Messages : 3 006
Points : 4 039
Points : 4 039
OK, je comprends mieux ton souci.

par contre je suis resté a la version 4.1, donc je peux pas trop te dire comment on peut s'en sortir avec les vues

bon courage

Michel
Cybher est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/08/2006, 15h46   #5
Membre éprouvé
 
Avatar de Christophe Charron
 
Homme Christophe Charron
Développeur informatique
Inscription : juillet 2005
Messages : 768
Détails du profil
Informations personnelles :
Nom : Homme Christophe Charron
Âge : 51
Localisation : France, Rhône (Rhône Alpes)

Informations professionnelles :
Activité : Développeur informatique
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : juillet 2005
Messages : 768
Points : 492
Points : 492
Citation:
Envoyé par Cybher
salut,

tu ne peux pas,sauf erreur de ma part mettre des alias directement apres le select

je ferais plus ceci :
Code :
1
2
3
4
5
SELECT
     MAX(nb) AS nb_max,
     MIN(nb) AS nb_min,
     ( MAX(nb) - MIN(nb) ) AS ecart
FROM tbl_nombres
Cette solution fonctionne au moins depuis la version 4.1...
__________________
Cordialement,
Christophe Charron
Pour consulter mon site professionnel, vous pouvez cliquer sur le bouton prévu à cet effet, juste sous la signature .
Christophe Charron est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/08/2006, 15h58   #6
Modérateur
 
Avatar de Cybher
 
Homme Michel
Consultant informatique
Inscription : mai 2005
Messages : 3 006
Détails du profil
Informations personnelles :
Nom : Homme Michel
Âge : 29
Localisation : France

Informations professionnelles :
Activité : Consultant informatique
Secteur : Conseil

Informations forums :
Inscription : mai 2005
Messages : 3 006
Points : 4 039
Points : 4 039
oui cela fonctionne mais ce n'est pas ce qu'il cherche...
Cybher est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/08/2006, 16h35   #7
Provisoirement toléré
 
Avatar de Maximilian
 
Inscription : juin 2003
Messages : 2 622
Détails du profil
Informations forums :
Inscription : juin 2003
Messages : 2 622
Points : 2 505
Points : 2 505
Salut,

Tu peux nous donner la requête qui pose problème ? Il y a peut-être moyen de la simplifier...
__________________
Pensez au bouton
Maximilian est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/08/2006, 17h16   #8
Candidat au titre de Membre du Club
 
Inscription : mai 2005
Messages : 30
Détails du profil
Informations forums :
Inscription : mai 2005
Messages : 30
Points : 12
Points : 12
en fait, c'était une question d'ordre général, parceque je rencontre ce besoin assez souvent:
pour l'affichage d'un bilan sous forme de tableau HTML, on a besoin de toutes les colonnes, notamment la colonne total qui est soit une somme, soit une différence, soit un calcul plus complexe avec les colonnes précédentes...

je fais donc l'opération nécessaire en PhP lorsque je récupère ma requète SQL, mais j'aurais justement aimé la faire directement dans la requète SQL, pour n'utiliser PhP que pour l'affichage HTML.

j'ai, par exemple pour afficher le bilan des congés pris par les employés sur l'année sélectionnée, une requète du type:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
SELECT s.id_salaries, CONCAT(s.prenom,' ',s.nom) AS nomcomplet,
 ( SELECT SUM(ad.nb)
   FROM absences_droits AS ad
   WHERE ad.id_salarie=s.id_salaries AND ad.annee='$annee' ) AS nb_acquis ,
 ( SELECT SUM(IF(type='conges',1,IF(type='demijournee',0.5,0))) 
   FROM absences AS a 
   WHERE a.id_salarie=s.id_salaries AND a.type IN ('conges','demijournee') AND a.annee='$annee' AND a.jour <= CURDATE()
   GROUP BY a.id_salarie ) AS nb_pris ,
 ( SELECT SUM(IF(type='conges',1,IF(type='demijournee',0.5,0))) 
   FROM absences AS a 
   WHERE a.id_salarie=s.id_salaries AND a.type IN ('conges','demijournee') AND a.annee='$annee' AND a.jour > CURDATE()
   GROUP BY a.id_salarie ) AS nb_aprendre 
FROM salaries AS s
ORDER BY nomcomplet
là, je ne peux bien évidemment pas recopier les champs nb_acquis, nb_pris et nb_aprendre pour faire:
Code :
1
2
3
 
$nb_prevu = $nb_pris + $nb_aprendre;
$nb_restant = $nb_acquis - $nb_prevu;
comme je suis encore sous MySql 4.1, je ne me suis pas encore plongé dans les nouvelles fonctions de MySql 5;
avez-vous une idée, des conseils?
fred23195 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/08/2006, 18h01   #9
Provisoirement toléré
 
Avatar de Maximilian
 
Inscription : juin 2003
Messages : 2 622
Détails du profil
Informations forums :
Inscription : juin 2003
Messages : 2 622
Points : 2 505
Points : 2 505
En utilisant des jointures plutôt que des sous-requêtes, les éléments de ton SELECT seraient certainement plus simples et plus facilement utilisables dans des opérations mathématiques.

Par ailleurs il y a plus de chances que l'optimiseur repère que "SUM(ad.nb)" et "SUM(ad.nb)" sont la même chose, qu'avec "SELECT SUM(ad.nb) FROM absences_droits as ad WHERE blabla..."
et "SELECT SUM(ad.nb) FROM absences_droits as ad WHERE blabla..."
__________________
Pensez au bouton
Maximilian est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/08/2006, 18h48   #10
Candidat au titre de Membre du Club
 
Inscription : mai 2005
Messages : 30
Détails du profil
Informations forums :
Inscription : mai 2005
Messages : 30
Points : 12
Points : 12
ha bin justement, çà m'intéresse !! c'est le deuxième gros problème que j'ai en ce moment...

j'avais justement commencé par des jointures pour éviter que cette requète soit si lourde, mais je n'ai pas trouvé la bonne syntaxe pour obtenir le bon résultat:
avec une seule jointure de la première table : LEFT JOIN absences_droits, là ça va...
mais dès que je rajoutais la deuxième jointure LEFT JOIN absences, je n'arrivais pas à choper les bons résultats, puisqu'il me sortait le produit cartésien :
Code :
1
2
3
4
5
6
7
8
9
 
SELECT s.id_salaries, CONCAT(s.prenom,' ',s.nom) AS nomcomplet,
SUM(ad.nb) AS nb_acquis ,
SUM(IF(a.type='conges',1,IF(a.type='demijournee',0.5,0))) AS nb_prevu
FROM salaries AS s
LEFT JOIN absences_droits AS ad ON s.id_salaries=ad.id_salarie AND ad.annee='$annee'
LEFT JOIN absences AS a ON s.id_salaries=a.id_salarie AND a.type IN ('conges','demijournee') AND a.annee='$annee' 
GROUP BY s.id_salaries
ORDER BY nomcomplet
après plusieurs essais, je n'ai pas obtenu les bons chiffres, j'ai donc abandonné pour me lancer dans les sous-requètes où là, pas de problème de produit cartésien...

quelle serait la bonne syntaxe de requète de jointure?
fred23195 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/08/2006, 16h16   #11
Provisoirement toléré
 
Avatar de Maximilian
 
Inscription : juin 2003
Messages : 2 622
Détails du profil
Informations forums :
Inscription : juin 2003
Messages : 2 622
Points : 2 505
Points : 2 505
Un truc de ce style peut-être (à l'arrache, pas testé) :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
SELECT s.id_salaries, CONCAT(s.prenom,' ',s.nom) AS nomcomplet,
SUM(ad.nb) AS nb_acquis,
SUM(IF(type='conges',1,IF(type='demijournee',0.5,0))) AS nb_pris,
SUM(IF(type='conges',1,IF(type='demijournee',0.5,0))) AS nb_aprendre,
 
FROM salaries AS s 
LEFT JOIN absences_droits AS ad
   ON ad.id_salarie=s.id_salaries 
LEFT JOIN absences AS a
   ON a.id_salarie=s.id_salaries
LEFT JOIN absences AS a2 
   ON a2.id_salarie=s.id_salaries
 
   WHERE ad.annee='$annee'
   AND a.type IN ('conges','demijournee') AND a.annee='$annee' AND a.jour <= CURDATE()
  AND a2.type IN ('conges','demijournee') AND a2.annee='$annee' AND a2.jour > CURDATE()
 
GROUP BY s.id_salarie
ORDER BY nomcomplet
__________________
Pensez au bouton
Maximilian 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 07h52.


 
 
 
 
Partenaires

Hébergement Web